如果iOS注册到UIBackgroundModes的位置,iOS会唤醒终止的应用程序吗?

我知道,如果应用程序使用“重大变更位置服务”,则即使应用程序终止,iOS也会将其唤醒。

如果应用程序使用标准的位置服务并将位置指定为UIBackgroundModes的关键字,则无法find有关此案例的明确答案:即使该应用程序已终止,iOS是否也会将其唤醒以提供更新? 还是应用程序需要在后台运行来获取位置更新callback?

更新:当时我问这个,我没有时间去testing它。 但是当我在这里得到一个答案后,我写了这段代码在我的应用程序的委托,看看我终止的应用程序将获得位置更新时重新启动。 当我收到更新通知时,我正在显示一个UILocalNotification。 然而,当我终止我的应用程序,然后改变我在城市的位置,应用程序不重新启动,我没有得到任何更新。 你能告诉我我做错了什么吗?

更新#2:根据本次问答的最终发现,这段代码没有任何问题,这是使用标准位置服务的应用程序的预期行为,不应在终止后重新启动。

我在Info.plist文件中添加了位置作为UIBackgroundModes之一。

这是我的应用程序委托的位置相关部分:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [UIApplication sharedApplication].applicationIconBadgeNumber = 0; m_locManager = [[CLLocationManager alloc] init]; m_locManager.delegate = self; [m_locManager startUpdatingLocation]; return YES; } - (void)applicationDidEnterBackground:(UIApplication *)application { [m_locManager startUpdatingLocation]; } - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { NSLog("%@", [NSString stringWithFormat:@"Background Fail %@", [error localizedDescription]]); } - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { UILocalNotification * theNotification = [[UILocalNotification alloc] init]; theNotification.alertBody = [NSString stringWithFormat:@"Background location %.06f %.06f %@" , newLocation.coordinate.latitude, newLocation.coordinate.longitude, newLocation.timestamp]; theNotification.alertAction = @"Ok"; theNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:1]; [[UIApplication sharedApplication] scheduleLocalNotification:theNotification]; } 

是的,它将以相同的方式运行,除非它会更频繁地接收更新(从而消耗更多的电量)。

来源:“ 跟踪用户的位置 ”部分下的“ 应用程序状态”和“多任务 ”。

编辑重新阅读后,似乎程序将从暂停状态唤醒,但不是终止的 。 不过,我不认为你真的需要这种背景模式。 它是专为需要很好的位置信息的应用程序而devise的(例如转向导航)。 请参阅位置编程指南中有关“基于区域”编程的部分。 你的评论中的例子被列为这个应用程序的用途之一。

再次编辑根据评论的讨论,最终的解决scheme似乎是设置重大的位置变化,直到用户足够接近,然后切换到良好的位置变化(并希望应用程序不会终止在这段时间^^ )

看起来像你find了一个可行的解决scheme,似乎使用重大的变化框架将节省您一些电池寿命,只要它是足够的准确,为您的目的。 您的解决scheme也是有益的,因为它只允许您监视可能超过每个应用程序限制的允许同时监视的20个区域,只监视您最接近的区域。

我需要类似的function,但不要认为重要的变化对我的应用程序来说是足够准确的,所以我挖了一些,发现了以下内容。

根据位置感知编程指南 ,在“监视基于形状的区域”下:

在iOS中,与您的应用程序相关联的区域会随时进行跟踪,包括您的应用程序未运行的时间。 如果应用程序未运行时跨越区域边界,则该应用程序将重新启动到后台以处理事件。 同样,如果应用程序在事件发生时被暂停,则会被唤醒并给予短时间来处理事件。

另外在“处理某一地区的跨界事件”中:

每当用户的当前位置穿越边界区域时,系统就会为您的应用程序生成适当的区域事件。 如果您的应用程序已经运行,则这些事件直接转到任何当前位置pipe理器对象的代表。 如果你的应用程序没有运行,系统将在后台启动它,以便它可以响应。 应用程序可以实现以下方法来处理边界交叉:

的LocationManager:didEnterRegion:

的LocationManager:didExitRegion:

在我的情况下,我只需要在边界交叉时触发通知,所以我将AppDelegate设置为符合CLLocationManagerDelegate,创build了locationManager属性,并将其放置在我的实现文件中:

 - (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.locationManager.delegate = self; return YES; } - (CLLocationManager *)locationManager { if (!_locationManager) { _locationManager = [[CLLocationManager alloc] init]; _locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters; } return _locationManager; } - (void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLRegion *)region { UILocalNotification *notification = [[UILocalNotification alloc] init]; notification.alertBody = NSLocalizedString(@"You crossed a boundary!", @"user crossed a boundary"); [[UIApplication sharedApplication] presentLocalNotificationNow:notification]; } 

testing显示这个工作没有UIBackgroundModes定位键需要设置。 在这种情况下,操作系统会为您处理边界监视,然后将事件发送到您的应用程序足够长的时间来处理事件。 这不会启动应用程序,它只是在后台运行它几秒钟来处理边界事件,在此期间,你只能做相关的活动。 希望这也能帮助别人!

一旦你杀了应用程序,位置更新被发送到应用程序

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 

您需要通过以下方式查找启动密钥来收集此代理方法内的位置更新,

 if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) { //Code to handle the location update } 

希望这是你要找的。 是的,您需要在plist中设置值为“位置更新的应用程序注册”的“所需的背景模式”键。