A Combine-based CoreLocation provider.
On every update of the device location from a wrapped CLLocationManager
,
it provides the latest location as a published CLLocation
object and
via a PassthroughSubject<CLLocation, Never>
called locationWillChange
.
Initialize and start the LocationProvider
import LocationProvider
let locationProvider = LocationProvider()
do {
try locationProvider.start()
}
catch {
// handle the lack of authorization, e.g. by
// locationProvider.requestAuthorization()
}
Potential location access authorization errors LocationProviderError.noAuthorization
need to be caught.
The standard location access user dialog can be brought up via
locationProvider.requestAuthorization()
Per default, it requests authorizedWhenInUse
-type access.
The LocationProvider
has a property onAuthorizationStatusDenied
that defines an action to be executed in case where location access is currently denied.
The default action is to present an alert (presentLocationSettingsAlert()
) that suggests to go to the app settings screen in order to change the location settings.
Subscribe to the locationWillChange
subject and store the returned Cancellable
cancellableLocation = locationProvider.locationWillChange.sink { loc in
// handleLocation(loc)
}
The function handleLocation
in the sink
closure would be executed on every CLLocation
object sent by the LocationProvider
.
Stop the LocationProvider
and cancel the subscription
locationProvider.stop()
cancellableLocation?.cancel()
Also, the LocationProvider
is an ObservableObject which has a @Published
property location
that updates the ObservableObject.
The observable LocationProvider
and its location
property can directly be accessed in SwiftUI:
import SwiftUI
import LocationProvider
struct ContentView: View {
@StateObject var locationProvider = LocationProvider()
var body: some View {
VStack{
Text("latitude \(locationProvider.location?.coordinate.latitude ?? 0)")
Text("longitude \(locationProvider.location?.coordinate.longitude ?? 0)")
}
.onAppear {
do {try locationProvider.start()}
catch {
print("No location access.")
locationProvider.requestAuthorization()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
In order for the app to have access to user location, the following keys should be set in Info.plist
:
NSLocationAlwaysAndWhenInUseUsageDescription
NSLocationAlwaysUsageDescription
NSLocationWhenInUseUsageDescription
Per default, the package requests location access in the background. Therefore, also add Location
to UIBackgroundModes
in Info.plist
or set locationProvider.lm.allowsBackgroundLocationUpdates = false
before starting the location updates via locationProvider.start()
.
A minimum working iOS App, using LocationProvider in SwiftUI can be found here: https://github.com/himbeles/LocationProviderExample
If you like this package and you would like to support me,