我正在编写一个监控用户位置的应用。我有一个使用startMonitoringSignificantLocationChanges的CLLocationManager对象,因此当应用程序未运行时,我可以从后台获取位置更新。我已经设置了我的应用程序didFinishLaunchingWithOptions,所以如果我得到一个位置键,我会启动我的经理以获取用户的位置。一切正常,但问题是,每次从背景获取位置时,此位置的水平精度非常差。在大多数情况下,它是1414米。
有人知道为什么当位置来自背景时水平精度如此糟糕? 我能做些什么来在后台获得更准确的位置吗?
当应用程序运行时,我得到的所有位置都非常准确,这只有在位置来自背景时才会发生。这与我在我所在城市的手机信号塔数量有什么关系吗?我想也许设备不使用gps的wifi节点来获取后台的位置。
无论如何,这里的任何帮助表示赞赏。 请分享您的想法。
谢谢!
答案 0 :(得分:14)
CLLocationManager
返回的位置的准确性取决于desiredAccuracy
,默认为kCLLocationAccuracyBest
,以及设备的可用精度。例如,如果设备的电池电量不足,您可能会获得不太准确的位置,或者如果它们仍然从其他应用程序缓存,您可能会获得更准确的位置。
但是,让您获得非常精确的坐标会耗尽电池的大量电量并耗尽设备。在后台应用可能仅限于更低的精度分辨率,以提高电池性能。
准确的位置需要大量电力才能使用GPS无线电,而不太准确的位置可能依赖于附近的WiFi热点和手机范围内的手机信号塔。
当您的应用程序从后台恢复时,系统将尝试提高您获得的结果的准确性。这是一个棘手的概念,但请查看手机上的地图应用程序。首先,代表您所在位置的圆圈非常大;随着系统更准确地了解您的位置,圆圈变小。此可视化表示手机使用更多功率来获得更精确的位置。
当您的应用从后台恢复时,您会看到与CLLocationManager
类似的现象:您将获得一个不准确的位置并接收后续更准确的更新。
在设计API时,Apple必须在便利性和电池寿命之间做出妥协。对用户位置的第一次更新可能不会那么准确,除非他们只是使用地图应用程序并且位置被缓存。
我能给你的最好建议是听取位置管理员的后续更新并相应地更新你的用户界面。祝你好运!
答案 1 :(得分:9)
如名称所示:startMonitoringSignificantLocationChanges通知仅用于通知您用户的位置与上一次检查的位置明显不同。当您收到通知以根据所需的准确度更新您的位置时,这是您的工作。通知不会为您执行此操作。它只是让你知道位置有变化,所以你可以相应地处理这种情况。如果您不知道如何获得更好的准确性,您可能需要查看LocateMe的Apple示例代码。这是一个存储准确性的片段(bestEffortAtLocation),然后在每次调用代理时测试准确性,直到获得更好的结果in或者超时发生。:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// store all of the measurements, just so we can see what kind of data we might receive
[locationMeasurements addObject:newLocation];
// 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];
}
}
// update the display with the new location data
}
归功于Apple,因为这是一个直接来自他们的示例代码LocateMe的片段:
因此,当您收到通知并需要获得更好的结果时,您需要更新准确性,看看是否能提供更好的结果。