/
CLLocationManager.swift
105 lines (82 loc) 路 3.15 KB
/
CLLocationManager.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import Combine
import CoreLocation
public extension CLLocationManager {
static func requestLocationAuthorization(
with manager: CLLocationManager = .init(),
type: AuthorizationType
) -> AnyPublisher<CLAuthorizationStatus, Never> {
AuthorizationPublisher(manager: manager, authorizationType: type)
.eraseToAnyPublisher()
}
enum AuthorizationType: String {
case always, whenInUse
}
}
protocol PublisherAuthorizationDelegate: class {
func send(status: CLAuthorizationStatus)
}
protocol SubscriptionAuthorizationDelegate: class {
func requestAuthorization(type: CLLocationManager.AuthorizationType)
}
final class AuthorizationSubscription <S: Subscriber>: NSObject,
PublisherAuthorizationDelegate,
Subscription where S.Input == CLAuthorizationStatus,
S.Failure == Never {
typealias Output = CLAuthorizationStatus
typealias Failure = Never
var subscriber: S?
private weak var delegate: SubscriptionAuthorizationDelegate?
private let authorizationType: CLLocationManager.AuthorizationType
init(
subscriber: S,
authorizationType: CLLocationManager.AuthorizationType,
delegate: SubscriptionAuthorizationDelegate
) {
self.subscriber = subscriber
self.delegate = delegate
self.authorizationType = authorizationType
}
func request(_ demand: Subscribers.Demand) {
delegate?.requestAuthorization(type: authorizationType)
}
func cancel() {
subscriber = nil
delegate = nil
}
func send(status: CLAuthorizationStatus) {
_ = subscriber?.receive(status)
}
}
final class AuthorizationPublisher: NSObject, Publisher, CLLocationManagerDelegate, SubscriptionAuthorizationDelegate {
typealias Output = CLAuthorizationStatus
typealias Failure = Never
private let manager: CLLocationManager
private let authorizationType: CLLocationManager.AuthorizationType
private weak var publisherAuthorizationDelegate: PublisherAuthorizationDelegate?
init(manager: CLLocationManager, authorizationType: CLLocationManager.AuthorizationType) {
self.manager = manager
self.authorizationType = authorizationType
}
func receive<S>(subscriber: S) where S: Subscriber, AuthorizationPublisher.Failure == S.Failure, AuthorizationPublisher.Output == S.Input {
let subscription = AuthorizationSubscription(
subscriber: subscriber,
authorizationType: authorizationType,
delegate: self
)
subscriber.receive(subscription: subscription)
publisherAuthorizationDelegate = subscription
}
// MARK: - CLLocationManagerDelegate
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
publisherAuthorizationDelegate?.send(status: status)
}
// MARK: - AuthorizationSubscriptionDelegate
func requestAuthorization(type: CLLocationManager.AuthorizationType) {
switch type {
case .whenInUse:
manager.requestWhenInUseAuthorization()
case .always:
manager.requestAlwaysAuthorization()
}
}
}