CLLocationManager和精度问题 - 有任何经验吗?

27

我的iPhone GPS存在一些准确性问题。我有一个应用程序使用了地理位置信息。

在委托方法locationManager:didUpdateToLocation:fromLocation:中,我会得到一个位置。通过一些研究,我发现即使将desiredAccuracy属性设置为kCLLocationAccuracyBest,GPS返回的第一个结果并不总是准确的。

为了解决这个问题,在它返回至少3次newLocation之前,我不会调用stopUpdatingLocation(这很快)。我还尝试使用其他两种“要求”来判断是否停止更新位置信息并返回newLocation。其中一种方法是检查newLocation的纬度和经度,与oldLocation进行比较,如果它们不相同,则继续运行位置更新。另一种方法是检查oldLocationnewLocation之间的距离,如果小于20米,则可以接受。这两种方法都测试了至少3次运行。后一种方法较为宽松,因为如果用户在移动车辆中,newLocationoldLocation很难完全相同。

现在,我的问题是,即使采取了以上措施(基本上不接受位置,直到CLLocationManager发生几次更新并检查CLLocations之间的距离(或它们是否相同),我仍然有时候看到一些奇怪的位置结果。

如果我离开应用程序,进入Maps.app使用GPS,然后打开多任务处理,强制退出我的应用程序,然后重新启动它进行干净的启动,这有时会解决问题。

有没有类似问题的经验和可能的解决方案?欢迎留下评论和解决方案:)

2个回答

45

我不记得我从哪个项目中获取了以下代码,但是这段代码对我非常有效(我记得它来自WWDC 2010的一个视频)。在我的代码中,我保留了原始项目中的评论,希望这能有所帮助。

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

希望这能帮到你!

此处参考自苹果公司的"Locate Me"示例项目中的GetLocationViewController.m文件。该项目可在以下网址获取:

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


啊,太好了!我应该更仔细地查看返回的CLLocation newLocation的属性,我没有意识到它也有一个时间戳。我可能会将其与我的代码一起使用。非常感谢! - runmad
1
这是苹果的“定位我”示例代码:https://developer.apple.com/library/ios/#samplecode/LocateMe/Listings/Classes_TrackLocationViewController_m.html#//apple_ref/doc/uid/DTS40007801-Classes_TrackLocationViewController_m-DontLinkElementID_14 - Garoal
kCLLocationAccuracyBest或kCLLocationAccuracyBestNavigation哪个更准确?我还需要速度。 - Van Du Tran
我的代码中 locationManager.desiredAccuracy 总是-1,为什么?顺便说一下,难道不应该是 manager.desiredAccuracy 吗? - Van Du Tran
@VanDuTran请阅读donkim代码中的注释。kCLLocationAccuracyBest具有负值。 - Giorgio

0

从donkim的回答中考虑替换这行代码

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

带有行

[NSObject cancelPreviousPerformRequestsWithTarget: self];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接