Ben Harris
Ben Harris

Reputation: 5684

CoreLocation Accuracy Woes

I have a program with a location manager set up like this:

self.locationManager = [[CLLocationManager alloc] init];
[locationManager startUpdatingLocation];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone; 
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;

I need the accuracy to within ten meters, however, it takes a few calls of the didUpdateToLocation delegate method to find the location at that accuracy. How would I go about delaying the call of this method or just indicate when the desired accuracy is achieved in order to proceed with the program.

Right now it tries proceeds with the first location returned. Even the second location update is not as accurate as expected.

Thanks in advance!

Upvotes: 6

Views: 4994

Answers (3)

mutatron
mutatron

Reputation: 553

I've recently tackled this problem and discovered, by cleverly reading the documentation at long last, that CoreLocation runs in a separate thread, so you can start it up and then retrieve events as it updates. It's in the documentation under the rubric "Getting the User's Location". So here's where you start updating:

- (void)startStandardUpdates
{
    if (nil == locationManager)
        locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyBest;
    locationManager.distanceFilter = none;
    [locationManager startUpdatingLocation];
}

If you make the delegate "self", it will send events to the same class where the start method is defined, so then you just have to add the following to retrieve the events:

- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
    fromLocation:(CLLocation *)oldLocation
{
    if (newLocation.horizontalAccuracy < 30.0)
    {
        NSLog(@"latitude %+.6f, longitude %+.6f\n",
                newLocation.coordinate.latitude,
                newLocation.coordinate.longitude);
        [manager stopUpdatingLocation];
    }
}

This way it will keep receiving events and then turn off the GPS receiver to save energy. Of course it needs a time out and some way to store and accept the location with the best horizontal accuracy if it times out, but I haven't figured out how to do that yet.

Upvotes: 4

Kevin
Kevin

Reputation: 2802

One strategy is to start a timer for a period long enough to get a fix (which will also be acceptable to the user)

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats

Start the location manager delivering updates. When the timer expires (or you get an acceptable accuracy) stop the updates and use that location.

It's probably the best you are going to get. You may want to give the user the option to try again for a location if it is still not accurate enough.

Upvotes: 2

Since each delegate call includes an accuracy figure, simply return from the method until your desired accuracy is reached (warning: that may never happen).

You can't simply jump to a ten meter result - there's a reason why it's called "desired" accuracy and not mandatory accuracy. You have to give it time to calculate more exact positions.

Upvotes: 7

Related Questions