CLLocationManager 和准确性问题 - 有什么经验吗?

发布于 2024-10-11 04:56:56 字数 931 浏览 6 评论 0原文

所以我正在处理 iPhone GPS 的一些准确性问题。我有一个使用位置的应用程序。

在委托方法 locationManager: didUpdateToLocation: fromLocation: 中,我返回了一个位置。经过一些研究,GPS 在返回的第一个结果中似乎并不总是准确的,即使将 desiredAccuracy 属性设置为 kCLLocationAccuracyBest 也是如此。

为了解决这个问题,在返回 newLocation: 之前我不会调用 stopUpdatingLocation 至少 3 次(这非常快)。我还尝试了另外两个“要求”,以确定是否停止UpdatingLocation 并返回newLocation。我尝试的一种方法是检查 newLocation 的纬度和经度,并与 oldLocation 进行比较,如果它们不相同,则保持位置更新运行。我还尝试检查 oldLocationnewLocation 之间的距离,如果小于 20 米,那就没问题。两者都经过至少 3 次运行的返回测试。后一种方式不太“严格”,因为如果用户位于移动的车辆中,newLocationoldLocation 很难达到 100% 相同。

现在,我的问题是,即使执行上述操作(基本上不接受位置,直到 CLLocationManager 上发生一些更新并检查 CLLocations 之间的距离(或是否相同)有时,在测试时,我仍然会看到一些奇怪的位置结果,

如果我离开应用程序,进入 Maps.app,使用 GPS,然后打开多任务处理,强制退出我的应用程序,然后有时会修复。重新打开它以获得一个干净的启动。

人们曾经使用过任何经验和可能的解决方案来解决同类问题吗?

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 :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

稀香 2024-10-18 04:56:56

我不记得我从哪个项目中获得了以下代码,但这对我来说非常有效(我记得它来自 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];
        }
    }
}

希望这有帮助!

通过 Apple 的“Locate Me”示例项目中的 GetLocationViewController.m,可从以下位置获取:

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

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

晌融 2024-10-18 04:56:56

从 donkim 的回答中考虑

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

用 line替换这一行

[NSObject cancelPreviousPerformRequestsWithTarget: self];

From donkim's answer consider replacing this line

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

with line

[NSObject cancelPreviousPerformRequestsWithTarget: self];
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文