Last active
July 13, 2023 09:15
-
-
Save fxm90/8b6c9753f12fcf19991f6c3f0cd635d3 to your computer and use it in GitHub Desktop.
Playground showing how to convert a delegate pattern to combine publishers.
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
// | |
// Combine-CLLocationManagerDelegate.playground | |
// | |
// Created by Felix Mau on 30.07.20. | |
// Copyright © 2020 Felix Mau. All rights reserved. | |
// | |
import PlaygroundSupport | |
import Combine | |
import CoreLocation | |
import Foundation | |
// Source: | |
// https://gist.github.com/fxm90/8b6c9753f12fcf19991f6c3f0cd635d3 | |
final class LocationManager: NSObject { | |
// MARK: - Public properties | |
/// Publisher reporting the latitude, longitude, and course information reported by the system. | |
/// | |
/// - Note: We hide any details to the underlying publisher by calling `eraseToAnyPublisher()`. | |
/// This makes sure our **public property** is **immutable**. | |
/// | |
/// - SeeAlso: https://developer.apple.com/documentation/corelocation/cllocation | |
var location: AnyPublisher<CLLocation, Error> { | |
locationSubject.eraseToAnyPublisher() | |
} | |
/// Publisher indicating the app's authorization to use location services. | |
/// | |
/// - Note: We hide any details to the underlying publisher by calling `eraseToAnyPublisher()`. | |
/// This makes sure our **public property** is **immutable**. | |
/// | |
/// - SeeAlso: https://developer.apple.com/documentation/corelocation/clauthorizationstatus | |
var authorizationStatus: AnyPublisher<CLAuthorizationStatus, Never> { | |
authorizationStatusSubject.eraseToAnyPublisher() | |
} | |
// MARK: - Private properties | |
/// **Private and mutable** publisher reporting the latitude, longitude, and course information reported by the system. | |
private let locationSubject = PassthroughSubject<CLLocation, Error>() | |
/// **Private and mutable** publisher indicating the app's authorization to use location services. | |
private let authorizationStatusSubject: CurrentValueSubject<CLAuthorizationStatus, Never> | |
// MARK: - Dependencies | |
private let locationManager: CLLocationManager | |
// MARK: - Initializer | |
override init() { | |
let locationManager = CLLocationManager() | |
self.locationManager = locationManager | |
authorizationStatusSubject = CurrentValueSubject(locationManager.authorizationStatus) | |
super.init() | |
locationManager.delegate = self | |
// For simplicity we assume that we're authorized to access location data and | |
// therefore start location updates immediately. | |
locationManager.startUpdatingLocation() | |
} | |
deinit { | |
locationManager.stopUpdatingLocation() | |
locationSubject.send(completion: .finished) | |
} | |
} | |
// MARK: - `CLLocationManagerDelegate` conformance | |
extension LocationManager: CLLocationManagerDelegate { | |
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) { | |
authorizationStatusSubject.send(status) | |
} | |
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { | |
guard let location = locations.last else { | |
// > If updates were deferred or if multiple locations arrived before they could be delivered, the array may contain additional entries. | |
// > The objects in the array are organized in the order in which they occurred. Therefore, the most recent location update is at the end | |
// > of the array. | |
// https://developer.apple.com/documentation/corelocation/cllocationmanagerdelegate/1423615-locationmanager | |
return | |
} | |
locationSubject.send(location) | |
} | |
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { | |
locationSubject.send(completion: .failure(error)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage example: