CLLocationManager y problemas de precisión: ¿alguna experiencia?

So I am dealing with some accuracy issues with iPhone GPS. I have an app which uses location.

In the delegate method locationManager: didUpdateToLocation: fromLocation: I am being returned a location. From a bit of research, it appears the GPS isn't always accurate on the first result it returns, even when setting desiredAccuracy propiedad a kCLLocationAccuracyBest.

In order to get around this, I don't call stopUpdatingLocation before it's returned newLocation: at least 3 times (this is very quick). I have also played around with two other "requirements" for whether to stopUpdatingLocation y devuelve el newLocation. One way I tried was to check the lat and long for newLocation y comparar con oldLocation and if these were not identical, then keep the location updating running. I also tried with checking the distance between the oldLocation y newLocation and if it's less than 20 meters, it's fine. Both of these are tested with the returning of at least 3 runs. The latter way is less "strict", since newLocation y oldLocation is quite hard to get away with being 100% identical if the user is in a moving vehicle.

Now, my issue is, that even when doing the above (basically not accepting a location, until a few updates have occured on CLLocationManager AND checking the distance between the CLLocations (or whether they are identical) I am still seeing somewhat weird results for locations sometimes, when testing.

It would be fixes sometimes if I leave the app, go into Maps.app, use the GPS, then open multitasking, force quit my app and then reopen it to get a clean launch.

Any experiences and possible solutions people have used to get around the same kind of issue? Comments and solutions appreciated :)

preguntado el 08 de enero de 11 a las 20:01

2 Respuestas

I don't remember which project it was exactly that I got the following code from, but this has worked for me really well (I do remember it was from a WWDC 2010 video). In my code, I left the comments from the original project in tact so hopefully this will help.

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    // test the age of the location measurement to determine if the measurement is cached
    // in most cases you will not want to rely on cached measurements
    NSTimeInterval locationAge = -[newLocation.timestamp timeIntervalSinceNow];

    if (locationAge > 5.0) return;

    // test that the horizontal accuracy does not indicate an invalid measurement
    if (newLocation.horizontalAccuracy < 0) return;

    // test the measurement to see if it is more accurate than the previous measurement
    if (bestEffortAtLocation == nil || bestEffortAtLocation.horizontalAccuracy > newLocation.horizontalAccuracy) {
        // store the location as the "best effort"
        self.bestEffortAtLocation = newLocation;

        // test the measurement to see if it meets the desired accuracy
        //
        // IMPORTANT!!! kCLLocationAccuracyBest should not be used for comparison with location coordinate or altitidue 
        // accuracy because it is a negative value. Instead, compare against some predetermined "real" measure of 
        // acceptable accuracy, or depend on the timeout to stop updating. This sample depends on the timeout.
        //
        if (newLocation.horizontalAccuracy <= locationManager.desiredAccuracy) {
            // we have a measurement that meets our requirements, so we can stop updating the location
            // 
            // IMPORTANT!!! Minimize power usage by stopping the location manager as soon as possible.
            //
            [self stopUpdatingLocation:NSLocalizedString(@"Acquired Location", @"Acquired Location")];

            // we can also cancel our previous performSelector:withObject:afterDelay: - it's no longer necessary
            [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(stopUpdatingLocation:) object:nil];
        }
    }
}

¡Espero que esto ayude!

Vía GetLocationViewController.m in Apple's "Locate Me" sample project, available at:

https://developer.apple.com/library/content/samplecode/LocateMe/Introduction/Intro.html

Respondido el 29 de junio de 17 a las 18:06

Ah, perfect! I should have looked more closely at the properties for the returned CLLocation newLocation, I didn't realize it also had a timeStamp. I'll probably use this one along with my own code. Thanks a bunch! - runmad

this is exactly what i am looking for. Thank you. - bselvan

Is kCLLocationAccuracyBest or kCLLocationAccuracyBestNavigation more accurate? I also need speed. - Van Du Tran

locationManager.desiredAccuracy is always -1 in my code, how come? and btw, isn't it supposed to be manager.desiredAccuracy? - Van Du Tran

From donkim's answer consider replacing this line

[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(stopUpdatingLocation:) object:nil];

with line

[NSObject cancelPreviousPerformRequestsWithTarget: self];

Respondido 16 Feb 13, 11:02

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.