Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
268 views
in Technique[技术] by (71.8m points)

ios - CLLocationManager and accuracy issues - any experiences?

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 property to 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 and return the newLocation. One way I tried was to check the lat and long for newLocation and compare to oldLocation and if these were not identical, then keep the location updating running. I also tried with checking the distance between the oldLocation and 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 and 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 :)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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];
        }
    }
}

Hope this helps!

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

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...