简体   繁体   中英

How do I track in the background in iOS a user walking and calculate the distance traveled so far using Swift and Xcode?

How do I track in the background in iOS a user walking in Apple MapKit or Google Maps Platform for iOS and calculate the distance traveled so far using Swift and Xcode?

I have tried using MapKit. The problem I get is that when the iOS device is locked, Core Location stops tracking the device. When the device is unlocked and the app comes to the foreground, Core Location starts tracking again and draws a straight line from the last point tracked to the point tracked when the app comes to the foreground, thus skipping all the time that the device is locked. If Google Maps Platform works better for this purpose, I am willing to use it.

Following is the relevant code:

override func viewDidLoad() {
    super.viewDidLoad()

    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.distanceFilter = kCLDistanceFilterNone
    locationManager.allowsBackgroundLocationUpdates = true
    if #available(iOS 11.0, *) {
        locationManager.showsBackgroundLocationIndicator = true
    }

    let status = CLLocationManager.authorizationStatus()

    if status == .authorizedAlways || status == .authorizedWhenInUse || status == .restricted {

        locationManager.startUpdatingLocation()
        locationManager.startMonitoringSignificantLocationChanges()

    } else {

        locationManager.requestAlwaysAuthorization()

    }

}

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {

    if status == .authorizedAlways || status == .authorizedWhenInUse || status == .restricted {

        locationManager.startUpdatingLocation()
        locationManager.startMonitoringSignificantLocationChanges()

    } else {

        locationManager.requestAlwaysAuthorization()

    }

}

Did you add in your .plist, Privacy - Location Always and When In Use Usage Description and Privacy - Location When In Use Usage Description ?

Then as you are probably conforming CLLocationManagerDelegate in the method didUpdateLocations you should be able to perform your code.

My mistake was that I was creating the line with the user location from the map instead of the user location passed to the didUpdateLocations method. The userLocation property on the map does not update in the background, whereas the userLocation property of CLLocationManager does update in the background.

Here is the corrected code, with a comment on the line that I corrected:

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

    print("didUpdateLocations", locations)

    if let userLocation = locations.first, polyline != nil {

        let userLocationMapPoint = MKMapPoint(userLocation.coordinate)
        let lastUserLocationMapPoint = MKMapPoint(route.last!)

        totalDistance += userLocationMapPoint.distance(to: lastUserLocationMapPoint)

        mapView.removeOverlay(polyline)

        route.append(userLocation.coordinate) // changed from route.append(mapView.userLocation.coordinate)

        polyline = MKPolyline(coordinates: route, count: route.count)

        mapView.addOverlay(polyline)

    }

    print("latitude:", mapView.userLocation.coordinate.latitude, "longitude:", mapView.userLocation.coordinate.longitude)

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM