Calculate Total Traveled Distance iOS Swift

2019-01-14 04:12发布

问题:

How can I calculate the total distance traveled use CoreLocation in Swift

I haven't been able to so far find any resources for how to do this in Swift for iOS 8,

How would you calculate the total distance moved since you began tracking your location?

From what I've read so far, I need to save location of a points, then calculate the distance between current point, and last point, then add that distance to a totalDistance variable

Objective-C is extremely unfamiliar to me, so I haven't been able to work out the swift syntax

Here is what I've worked out so far, not sure if I'm doing it right. Though the distanceFromLocationmethod is returning all 0.0 so obviously something is wrong

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
     var newLocation: CLLocation = locations[0] as CLLocation

    oldLocationArray.append(newLocation)
           var totalDistance = CLLocationDistance()
    var oldLocation = oldLocationArray.last

    var distanceTraveled = newLocation.distanceFromLocation(oldLocation)

    totalDistance += distanceTraveled

 println(distanceTraveled)



}

回答1:

update: Xcode 8.3.2 • Swift 3.1

The problem there is because you are always getting the same location over and over again. Try like this:

import UIKit
import MapKit

class ViewController: UIViewController,  CLLocationManagerDelegate {
    @IBOutlet weak var mapView: MKMapView!
    let locationManager = CLLocationManager()
    var startLocation: CLLocation!
    var lastLocation: CLLocation!
    var startDate: Date!
    var traveledDistance: Double = 0
    override func viewDidLoad() {
        super.viewDidLoad()
        if CLLocationManager.locationServicesEnabled() {
            locationManager.delegate = self
            locationManager.desiredAccuracy = kCLLocationAccuracyBest
            locationManager.requestWhenInUseAuthorization()
            locationManager.startUpdatingLocation()
            locationManager.startMonitoringSignificantLocationChanges()
            locationManager.distanceFilter = 10
            mapView.showsUserLocation = true
            mapView.userTrackingMode = .follow
        }
    }
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if startDate == nil {
            startDate = Date()
        } else {
            print("elapsedTime:", String(format: "%.0fs", Date().timeIntervalSince(startDate)))
        }
        if startLocation == nil {
            startLocation = locations.first
        } else if let location = locations.last {
            traveledDistance += lastLocation.distance(from: location)
            print("Traveled Distance:",  traveledDistance)
            print("Straight Distance:", startLocation.distance(from: locations.last!))
        }
        lastLocation = locations.last
    }
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        if (error as? CLError)?.code == .denied {
            manager.stopUpdatingLocation()
            manager.stopMonitoringSignificantLocationChanges()
        }
    }
}

Sample Project



回答2:

If you want to calculate the route distance between two points you need to use MKDirectionsRequest, this will return you one, or many, routes from point A to point B with the step by step instruction:

class func caculateDistance(){
    var directionRequest = MKDirectionsRequest()
    var sourceCoord = CLLocationCoordinate2D(latitude: -36.7346287, longitude: 174.6991812)
    var destinationCoord = CLLocationCoordinate2D(latitude: -36.850587, longitude: 174.7391745)
    var mkPlacemarkOrigen = MKPlacemark(coordinate: sourceCoord, addressDictionary: nil)
    var mkPlacemarkDestination = MKPlacemark(coordinate: destinationCoord, addressDictionary: nil)
    var source:MKMapItem = MKMapItem(placemark: mkPlacemarkOrigen)
    var destination:MKMapItem = MKMapItem(placemark: mkPlacemarkDestination)
    directionRequest.setSource(source)
    directionRequest.setDestination(destination)
    var directions = MKDirections(request: directionRequest)
    directions.calculateDirectionsWithCompletionHandler {
        (response, error) -> Void in
        if error != nil { println("Error calculating direction - \(error.localizedDescription)") }
        else {
            for route in response.routes{
                println("Distance = \(route.distance)")
                for step in route.steps!{
                    println(step.instructions)
                }  
            }
        }
    }
}

This example code will return you this:

Distance
Distance = 16800.0

Step by Step instructions
Start on the route
At the end of the road, turn left onto Bush Road
Turn right onto Albany Expressway
At the roundabout, take the first exit onto Greville Road toward 1, Auckland
At the roundabout, take the third exit to merge onto 1 toward Auckland
Keep left
Take exit 423 onto Shelly Beach Road
Continue onto Shelly Beach Road
At the end of the road, turn right onto Jervois Road
Turn left onto Islington Street
Keep right on Islington Street
Arrive at the destination

The function can be easily modified to receive two locations and return the distance and any other needed information.

I hope that helps you!



回答3:

Leo Dabus method could be used to calculate the geographical distance between your actual location and start one.

In order to obtain the precise traveled distance, you have to update "traveledDistance" using the difference between the last position and the old one.

This is my implementation:

var startLocation:CLLocation!
var lastLocation: CLLocation!
var traveledDistance:Double = 0

func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
    if startLocation == nil {
        startLocation = locations.first as! CLLocation
    } else {
        let lastLocation = locations.last as! CLLocation
        let distance = startLocation.distanceFromLocation(lastLocation)
        startLocation = lastLocation
        traveledDistance += distance 
    }
}