我们目前正在开发一个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:
有什么关系,但我不确定它是否是,或者如何解决(如果的确如此)。预先感谢您的帮助!
您应该将UIBackgroundMode添加到您的info.plist文件中,并将您的应用程序标识为背景位置应用程序。 – J2theC
谢谢,J2theC,但是我们已经为'所需的背景模式'设置了'位置更新的应用寄存器'。 (我会编辑问题以清楚地说明这一点)。位置更新应该是他们应该做的,只是这个永无止境的后台任务就是问题所在。 – dvyio
我很确定你的实例变量'bgTask'在应用程序回到前台时被重新分配,所以这个值不包含你想要杀死的标识符。考虑将这个标识符保存在'NSUserDefaults'中,或者更长一些。 – Hyperbole