Trying to get current location with using swiftUI. Below code, couldn't initialize with didUpdateLocations delegate.
class GetLocation : BindableObject {
var didChange = PassthroughSubject<GetLocation,Never>()
var location : CLLocation {
didSet {
didChange.send(self)
}
}
init() {}
}
To display a map with the region of your choosing, follow these steps: import MapKit. Add a @State property to define a variable named region as a MKCoordinateRegion that specifies the center coordinate and zoom level for the map. Add a Map element to the body of the MapView and use the region as a parameter.
You need to add a key NSLocationWhenInUseUsageDescription in yours info. plist file and in the value you write something that you want to show the user in the popup dialog. You need to test it on a real device cause Simulator accepts only custom locations. Select the Simulator -> Debug -> Location -> Custom Location...
I have written a one-file swift package with usage instructions on https://github.com/himbeles/LocationProvider. It provides a ObservableObject
-type wrapper class for CLLocationManager and its delegate.
There is a @Published
property location
which can directly be used in SwiftUI, as well as a PassthroughSubject<CLLocation, Never>
called locationWillChange
that you can subscribe to via Combine. Both update on every didUpdateLocations
event of the CLLocationManager
.
It also handles the case where location access has previously been denied: The default behavior is to present the user with a request to enable access in the app settings and a link to go there.
In SwiftUI (> iOS 14, > macOS 11), use as
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()
}
}
}
}
This code below works (Not production ready). Implementing the CLLocationManagerDelegate
works fine and the lastKnownLocation
is updated accordingly.
Don't forget to set the NSLocationWhenInUseUsageDescription
in your Info.plist
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
private let manager = CLLocationManager()
var lastKnownLocation: CLLocation?
func startUpdating() {
manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
print(locations)
lastKnownLocation = locations.last
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
if status == .authorizedWhenInUse {
manager.startUpdatingLocation()
}
}
}
As of Xcode 11 beta 4, you will need to change didChange
to willChange
:
var willChange = PassthroughSubject<LocationManager, Never>()
var lastKnownLocation: CLLocation? {
willSet {
willChange.send(self)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With