我们目前正在开发一个需要在后台检查位置的 iOS 应用程序。起初,我们尝试使用重大的位置变化,但它们不够准确/触发频率不够。我们考虑过使用区域监控,但根据我在网上阅读的内容,这也不总是准确的,而且您还存在要监控的区域数量有限的问题。(我们最终可能会尝试区域监控。)然而,目前,我们正在尝试使用标准位置更新来在后台跟踪用户位置,并计划每隔 5 分钟左右检查一次。 .
该应用程序在后台注册位置更新(使用“应用程序注册位置更新”作为“必需的后台模式”),我们启动一个后台任务,它检查一次位置,停止位置更新,然后使用NSThread sleepForTimeInterval:
(目前,而我们正在开发中)暂停任务 10 秒。然后它再次检查位置,停止位置更新,暂停 10 秒等。
这似乎按预期工作......当应用程序进入后台时,我们会每 10 秒收到一个包含位置更新的日志/通知,当应用程序重新打开时,日志/通知会停止。然而,问题是当应用程序第二次进入后台时,原来的后台任务似乎从未取消,并创建了一个新任务,所以现在有两个任务在运行,每个任务在 10 秒时检查位置在间隔上。如果应用程序多次打开/发送到后台,则会为每个应用程序启动一个后台任务。
我考虑过设置一个标志来说明“应用程序是否已至少发送到后台一次?”,并且仅在第一次将其发送到后台时才运行该任务,但这似乎会导致其他问题,并且(如一个相对较新的iOS开发人员)我很好奇为什么当应用程序进入前台时后台任务没有被取消。
AppDelegate.h 文件包含...
@interface AppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate> {
UIWindow *window;
UINavigationController *navigationController;
UIBackgroundTaskIdentifier bgTask;
BOOL inBackground;
}
AppDelegate.m 文件包含...
- (void)applicationDidEnterBackground:(UIApplication *)application {
inBackground = YES;
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (inBackground == YES) {
NSLog(@"%@", @"Check location...");
[locationManager startUpdatingLocation];
[NSThread sleepForTimeInterval:10];
}
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
});
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
inBackground = NO;
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
}
位置更新按预期工作,我只是无法弄清楚为什么当应用程序进入前台时后台任务没有被取消/结束。我确实想知道这是否与 . 有任何关系NSThread sleepForTimeInterval:
,但我不确定是否是,或者如何修复它(如果确实如此)。提前感谢您的帮助!