Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add publisher for location updates
- Loading branch information
Showing
2 changed files
with
101 additions
and
86 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import Combine | ||
import CoreLocation | ||
|
||
protocol PublisherLocationDelegate: class { | ||
func startLocationUpdates() | ||
} | ||
|
||
protocol SubscriptionLocationDelegate: class { | ||
func didUpdate(with locations: [CLLocation]) | ||
func didFail(with error: Error) | ||
} | ||
|
||
final class LocationSubscription <S: Subscriber>: | ||
NSObject, | ||
SubscriptionLocationDelegate, | ||
Subscription where S.Input == [CLLocation], | ||
S.Failure == Error { | ||
|
||
var subscriber: S? | ||
private weak var publisherDelegate: PublisherLocationDelegate? | ||
|
||
init(subscriber: S?, delegate: PublisherLocationDelegate?) { | ||
self.subscriber = subscriber | ||
self.publisherDelegate = delegate | ||
} | ||
|
||
func didUpdate(with locations: [CLLocation]) { | ||
_ = subscriber?.receive(locations) | ||
} | ||
|
||
func didFail(with error: Error) { | ||
_ = subscriber?.receive(completion: .failure(error)) | ||
} | ||
|
||
func request(_ demand: Subscribers.Demand) { | ||
publisherDelegate?.startLocationUpdates() | ||
} | ||
|
||
func cancel() { | ||
subscriber = nil | ||
publisherDelegate = nil | ||
} | ||
|
||
} | ||
|
||
final class LocationPublisher: NSObject, | ||
Publisher, | ||
CLLocationManagerDelegate, | ||
PublisherLocationDelegate { | ||
typealias Output = [CLLocation] | ||
typealias Failure = Error | ||
|
||
private let manager: CLLocationManager | ||
private weak var subscriberDelegate: SubscriptionLocationDelegate? | ||
|
||
init(manager: CLLocationManager) { | ||
self.manager = manager | ||
super.init() | ||
self.manager.delegate = self | ||
} | ||
|
||
// MARK: Publisher | ||
|
||
func receive<S>(subscriber: S) where S : Subscriber, LocationPublisher.Failure == S.Failure, LocationPublisher.Output == S.Input { | ||
let subscibtion = LocationSubscription( | ||
subscriber: subscriber, | ||
delegate: self | ||
) | ||
subscriber.receive(subscription: subscibtion) | ||
subscriberDelegate = subscibtion | ||
} | ||
|
||
// MARK: CLLocationManagerDelegate | ||
|
||
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { | ||
subscriberDelegate?.didFail(with: error) | ||
manager.stopUpdatingLocation() | ||
} | ||
|
||
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { | ||
subscriberDelegate?.didUpdate(with: locations) | ||
} | ||
|
||
// MARK: PublisherLocationDelegate | ||
|
||
func startLocationUpdates() { | ||
manager.startUpdatingLocation() | ||
} | ||
} | ||
|
||
|