I want to build a view with a map centered on the user location when loaded. I managed to build this, but sometimes the map loads with latitude 0, longitude: 0. This happens when I move too fast between views (there are other views in the project besides the map).
It feels like the user location is loaded too slow and the Map appears with default coordinates, but I really have no idea what I'm doing wrong. Any ideas?
Map view:
import SwiftUI
import MapKit
struct MapView: View {
@StateObject var locationManager = LocationManager()
@State var trackingMode: MapUserTrackingMode = .follow
var body: some View {
Map(coordinateRegion: $locationManager.region, interactionModes: .all, showsUserLocation: true, userTrackingMode: $trackingMode)
}
}
Location View Model:
import SwiftUI
import CoreLocation
import MapKit
class LocationManager: NSObject, ObservableObject, CLLocationManagerDelegate {
@Published var region = MKCoordinateRegion()
private let manager = CLLocationManager()
override init() {
super.init()
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
locations.last.map {
let center = CLLocationCoordinate2D(latitude: $0.coordinate.latitude, longitude: $0.coordinate.longitude)
let span = MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2)
region = MKCoordinateRegion(center: center, span: span)
}
}
}
That is exactly your problem. Location data will ALWAYS lag, just like any other retrieved data. What you need to consider is a mechanism to update your views when you get updates.
The best way to do that is to import Combine
in your LocationManager
class and use a PassthroughSubject
like this:
let objectWillChange = PassthroughSubject<Void, Never>()
@Published var region = MKCoordinateRegion() {
willSet { objectWillChange.send() }
}
That allows you to subscribe to your publisher in the map and get updates. You will find many tutorials regarding this.