Skip to content

Commit

Permalink
feat: add combine location manager extension
Browse files Browse the repository at this point in the history
  • Loading branch information
gtokman committed May 5, 2021
1 parent 8e89936 commit b50e0c8
Showing 1 changed file with 104 additions and 0 deletions.
104 changes: 104 additions & 0 deletions Sources/ExtensionKit/CoreLocation/CLLocationManager.swift
@@ -0,0 +1,104 @@
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
)
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()
}
}
}

0 comments on commit b50e0c8

Please sign in to comment.