56 lines
1.4 KiB
Swift
56 lines
1.4 KiB
Swift
// Copyright 2024-present 650 Industries. All rights reserved.
|
|
|
|
import CoreLocation
|
|
import ExpoModulesCore
|
|
|
|
internal class LocationsStreamer: BaseStreamer {
|
|
typealias LocationsStream = AsyncThrowingStream<[CLLocation], Error>
|
|
|
|
private var locationsStream: LocationsStream?
|
|
private var continuation: LocationsStream.Continuation?
|
|
|
|
deinit {
|
|
if continuation != nil {
|
|
stopStreaming()
|
|
}
|
|
}
|
|
|
|
func streamLocations() throws -> LocationsStream {
|
|
if !CLLocationManager.locationServicesEnabled() {
|
|
throw Exceptions.LocationServicesDisabled()
|
|
}
|
|
|
|
if let stream = locationsStream {
|
|
return stream
|
|
}
|
|
let stream = LocationsStream { continuation in
|
|
self.continuation = continuation
|
|
manager.startUpdatingLocation()
|
|
}
|
|
locationsStream = stream
|
|
return stream
|
|
}
|
|
|
|
override func stopStreaming() {
|
|
manager.stopUpdatingLocation()
|
|
continuation?.finish()
|
|
|
|
locationsStream = nil
|
|
continuation = nil
|
|
}
|
|
|
|
// MARK: - CLLocationManagerDelegate
|
|
|
|
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
|
if !locations.isEmpty {
|
|
continuation?.yield(locations)
|
|
}
|
|
}
|
|
|
|
func locationManager(_ manager: CLLocationManager, didFailWithError error: any Error) {
|
|
continuation?.finish(throwing: Exceptions.LocationUnavailable().causedBy(error))
|
|
locationsStream = nil
|
|
continuation = nil
|
|
}
|
|
}
|