I am trying to use the distanceFromLocation: method to calculate the total distance that I am walking with my iPhone in my hand. So far, I have been searching all over to help remedy my confusing, inaccurate, and seemingly arbitrary results. In these code snippets, theLabel is just a label object that is present in my app's interface, distanceMoved is the variable that I am trying to store the total distance I walked in, and locMan is a location manager that is declared in my @interface file.
- (void)viewDidLoad
{
locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
[locMan startUpdatingLocation];
isInitial = true;
distanceMoved = 0.0;
[super viewDidLoad];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
distanceMoved += [newLocation distanceFromLocation: oldLocation];
theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved];
}
Any help for fixing what I am doing wrong here would be greatly appreciated. Thank you!
kCLLocationAccuracyBest
,oldLocation
is nil.There's more you could do but this should work provided you get a good enough horizonalAccuracy (<30m). You could filter out low accuracy results but then you'd have to keep track of the oldLocation yourself which is a bit more complicated.
Add an NSLog (see below) so you can find out what's happening. If you still don't get good results post the output of the NSLog so we can see what's going on and help more.
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow];
if (age > 120) return; // ignore old (cached) updates
if (newLocation.horizontalAccuracy < 0) return; // ignore invalid udpates
// EDIT: need a valid oldLocation to be able to compute distance
if (oldLocation == nil || oldLocation.horizontalAccuracy < 0) return;
CLLocationDistance distance = [newLocation distanceFromLocation: oldLocation];
NSLog(@"%6.6f/%6.6f to %6.6f/%6.6f for %2.0fm, accuracy +/-%2.0fm",
oldLocation.coordinate.latitude,
oldLocation.coordinate.longitude,
newLocation.coordinate.latitude,
newLocation.coordinate.longitude,
distance,
newLocation.horizontalAccuracy);
distanceMoved += distance;
theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved];
}
- (void)viewDidLoad
{
locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
locMan.desiredAccuracy = kCLLocationAccuracyBest;
locMan.distanceFilter = 10;
[locMan startUpdatingLocation];
isInitial = true;
distanceMoved = 0.0;
[super viewDidLoad];
}
EDIT for iOS6 if you wanted to do the same using didUpdateLocations: (since the above method is now deprecated) the simplest solution is to simply save each location in a property so that on the next update you have the previous location. Declare an property in the class to hold the oldLocation
:
@property (nonatomic, retain) CLLocation* oldLocation;
Then in the delegate method you save each newLocation
for use as the oldLocation
for the next time the delegate method is called:
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocations:(NSArray *)locations
{
CLLocation* newLocation = [locations lastObject];
NSTimeInterval age = -[newLocation.timestamp timeIntervalSinceNow];
if (age > 120) return; // ignore old (cached) updates
if (newLocation.horizontalAccuracy < 0) return; // ignore invalid udpates
// EDIT: need a valid oldLocation to be able to compute distance
if (self.oldLocation == nil || self.oldLocation.horizontalAccuracy < 0) {
self.oldLocation = newLocation;
return;
}
CLLocationDistance distance = [newLocation distanceFromLocation: self.oldLocation];
NSLog(@"%6.6f/%6.6f to %6.6f/%6.6f for %2.0fm, accuracy +/-%2.0fm",
self.oldLocation.coordinate.latitude,
self.oldLocation.coordinate.longitude,
newLocation.coordinate.latitude,
newLocation.coordinate.longitude,
distance,
newLocation.horizontalAccuracy);
distanceMoved += distance;
theLabel.text = [NSString stringWithFormat: @"%f meters", distanceMoved];
self.oldLocation = newLocation; // save newLocation for next time
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With