The CoreLocation module always fails to fetch my phone’s real location accurately, and the location shown by showUserLocation always has a slight deviation.
The code of LocationViewModel.swift
import Foundation
import CoreLocation
import Combine
class LocationViewModel: NSObject, ObservableObject, CLLocationManagerDelegate {
private let locationManager = CLLocationManager()
@Published var location: Location?
@Published var authorizationStatus: CLAuthorizationStatus?
@Published var errorMessage: String?
@Published var gpsSignalStatus: String = "Detecting GPS signal..."
override init() {
super.init()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
checkAuthorizationStatus()
}
func checkAuthorizationStatus() {
authorizationStatus = locationManager.authorizationStatus
switch authorizationStatus {
case .authorizedWhenInUse, .authorizedAlways:
locationManager.startUpdatingLocation()
locationManager.startUpdatingHeading()
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
case .denied, .restricted:
errorMessage = "The authorization of location is limited。Please turn it on in settings"
default:
errorMessage = "Unknown location authorization status"
}
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
checkAuthorizationStatus()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else { return }
self.location = Location(
coordinate: location.coordinate,
altitude: location.altitude,
speed: location.speed,
direction: location.course,
horizontalAccuracy: location.horizontalAccuracy,
timestamp: location.timestamp
)
if location.horizontalAccuracy < 0 {
gpsSignalStatus = "GPS is not avaliable"
} else if location.horizontalAccuracy > 100 {
gpsSignalStatus = "GPS signal is weak."
} else {
gpsSignalStatus = "GPS signal is great."
}
}
func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
if var currentLocation = self.location {
currentLocation.direction = newHeading.trueHeading
self.location = currentLocation
}
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
print("Failed to find user's location: (error.localizedDescription)")
}
}
The code of LocationView.swift
...
struct MapView: View {
@ObservedObject var viewModel: LocationViewModel
@State var cameraPosition: MapCameraPosition = .automatic
var body: some View {
ZStack {
Map(position: $cameraPosition) {
if let coordinate = viewModel.location?.coordinate {
Annotation("MyLocation", coordinate: CLLocationCoordinate2D(latitude: coordinate.latitude, longitude: coordinate.longitude)) {
Text("The position which CoreLocation got")
}
}
}
.onReceive(viewModel.location.publisher) { location in
cameraPosition = .region(MKCoordinateRegion(
center: location.coordinate,
span: MKCoordinateSpan(latitudeDelta: 0.0025, longitudeDelta: 0.0025)
))
}
}
}
}
...
The position obtained from CoreLocation has an error of several hundred meters compared to the actual position.
- Any problem in my code?
- Is there a way to obtain the right location?
New contributor
Kinda Hall is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.