-->

CoreLocation Negative Values

2019-07-01 10:14发布

问题:

I am using the CoreLocation framework to get my speed and distance to calculate average speed.

On the first update that CoreLocation sends out, it shows negative values for both speed and distance traveled. How can I fix this?

Speed is locationController.locationManager.location.speed where locationController holds my CoreLocation delegate. Distance is calculated by taking the old location and the new location and calculating distance.

//Distance
- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
           fromLocation:(CLLocation *)oldLocation
{
    // make sure the old and new coordinates are different
    if ((oldLocation.coordinate.latitude != newLocation.coordinate.latitude) &&
        (oldLocation.coordinate.longitude != newLocation.coordinate.longitude))
    {         
        mDistance = [newLocation distanceFromLocation:oldLocation];
    }
}

回答1:

The data returned by Core Location may be invalid for a number of reasons. Before you use the data, run this method to see if it is valid.

// From http://troybrant.net/blog/2010/02/detecting-bad-corelocation-data/
- (BOOL)isValidLocation:(CLLocation *)newLocation
        withOldLocation:(CLLocation *)oldLocation 
{
    // filter out nil locations
    if (!newLocation){
        return NO;
    }
    // filter out points by invalid accuracy
    if (newLocation.horizontalAccuracy < 0){
        return NO;
    }
    // filter out points that are out of order
    NSTimeInterval secondsSinceLastPoint = [newLocation.timestamp 
                                            timeIntervalSinceDate:oldLocation.timestamp];
    if (secondsSinceLastPoint < 0){
        return NO;
    }
    // filter out points created before the manager was initialized
    NSTimeInterval secondsSinceManagerStarted = [newLocation.timestamp 
                                                 timeIntervalSinceDate:locationManagerStartDate];
    if (secondsSinceManagerStarted < 0){
        return NO;
    }
    // newLocation is good to use
    return YES;
} 


回答2:

There's a note in the CLLocationManager Class Reference:

Because it can take several seconds to return an initial location, the location manager typically delivers the previously cached location data immediately and then delivers more up-to-date location data as it becomes available. Therefore it is always a good idea to check the timestamp of any location object before taking any actions.

You should check whether you're getting a cached value and ignore it, waiting for the first "real" update.

NSTimeInterval timeSinceLastUpdate = [[newLocation timestamp] timeIntervalSinceNow];

// If the information is older than a minute, or two minutes, or whatever
// you want based on expected average speed and desired accuracy, 
// don't use it.
if( timeSinceLastUpdate < -60 ){
    return;
}


回答3:

If you are collecting the first point, it has no reference to calculate speed or distance. I believe it is defined to return -1 if it can't get you what you need.

To resolve this, simply check for the negative values.

if(location.speed > 0) {
    return;
}