我正在尝试构建一个iPhone应用程序,要求我始终使用Core Location跟踪用户的位置。我正在使用 startMonitoringSignificantLocationChanges ,以便它在后台进行更新,因为准确性不如每当发生重大变化时更新那么重要。
目前,我向Web服务发出HTTP请求以更新位置。这在我运行应用程序时非常有效 - 我的位置在MySQL数据库中更新我正在存储位置数据。但是当应用程序进入后台时 - 我可以在手机的右上角看到位置服务图标仍在运行,但当我回去查看数据库时,它根本没有更新我的位置。我通过驾车穿越城镇,以应用程序运行的一种方式,以及在后台运行应用程序的方式来测试这一点。
来自Apple的文档:
如果您使此服务保持运行并且您的应用程序随后被暂停或终止,则当新位置数据到达时,该服务会自动唤醒您的应用程序。在唤醒时,您的应用程序将被置于后台并给予少量时间来处理位置数据。由于您的应用程序位于后台,因此应该执行最少的工作并避免任何可能阻止其在分配的时间到期之前返回的任务(例如查询网络)。如果没有,您的申请可能会被终止。
这个“处理位置数据的时间有多短”到底有多长?是不是建议不要查询网络,还是不可能在那段时间查询网络?即使应用程序在后台,有没有更好的方法来跟踪几个不同用户的位置?
答案 0 :(得分:4)
你应该看一下后台任务。
当Apple说small amount of time to process location data
时,在locationManager:didUpdateToLocation:fromLocation:
方法返回后,您不应该真正依赖于获取任何处理时间。假设您在一个单独的线程中异步运行HTTP请求,您可能没有足够的时间在应用程序暂停之前完成它。
UIBackgroundTasks让您在后台询问操作系统的额外处理时间。发出HTTP请求可能是一项任务。时间限制是10分钟,但不能保证你得到这么多时间。
在您的位置回调中,您应为您的请求定义新的后台任务。如果操作系统确定它不能再为您提供处理时间,则会随时触发到期处理程序块。
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
// Start your request here
UIBackgroundTaskIdentifier backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
backgroundTask = UIBackgroundTaskInvalid;
// Cancel your request here
}];
}
当请求完成后,您应该告诉应用程序任务已完成:
- (void)requestFinished:(id)request {
[[UIApplication sharedApplication] endBackgroundTask:backgroundTask];
backgroundTask = UIBackgroundTaskInvalid;
}
在此示例中,我没有考虑到您可能会在请求完成之前收到多个位置回调。如果发生这种情况,您需要在开始新任务之前取消该请求和当前后台任务,或者为每个请求创建单独的后台任务。
另一种方法是在位置回调方法中在主线程上同步运行HTTP请求,但由于多种原因这样做是件坏事,比如在用户打开应用程序时锁定界面请求正在运行。