【发布时间】:2012-08-19 02:34:35
【问题描述】:
我们目前正在开发一个需要在后台检查位置的 iOS 应用。起初,我们尝试使用重大的位置变化,但它们不够准确/触发频率不够高。我们考虑过使用区域监控,但从我在网上阅读的内容来看,这也不总是准确的,而且您还存在要监控的区域数量有限的问题。 (我们最终可能会尝试区域监控。)然而,目前,我们正在尝试使用标准位置更新来在后台跟踪用户位置,并计划每隔 5 分钟左右检查一次。 .
应用程序在后台注册位置更新(使用“应用程序注册位置更新”作为“必需的后台模式”),我们启动一个后台任务,它检查一次位置,停止位置更新,然后使用@987654321 @to(目前,我们正在开发中)暂停任务 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,但我们已经为“所需的后台模式”提供了“用于位置更新的应用程序注册”。 (我将编辑问题以明确这一点。)位置更新按应有的方式发生,只是这个永无止境的后台任务才是问题所在。
-
我很确定当应用程序回到前台时您的实例变量
bgTask正在重新分配,因此该值不包含您要杀死的标识符。考虑将此标识符保存在NSUserDefaults或更永久的位置。
标签: objective-c ios background location nsthread