24

我知道如果一个应用程序使用“重大变化的位置服务”,如果有一个位置更新要传递,iOS 会唤醒它,即使应用程序被终止。

如果应用程序使用标准位置服务并将位置指定为 UIBackgroundModes 的键,我无法找到有关此案的明确答案:即使它被终止,iOS 也会唤醒它以提供更新吗?还是应用程序需要在后台运行才能获取位置更新回调?

更新:当我问这个时,我没有时间测试它。但是在这里得到答案后,我在我的应用程序的委托中编写了这段代码,以查看我终止的应用程序在获得位置更新时是否会重新启动。当我收到更新通知时,我正在显示 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];
}
4

3 回答 3

5

看起来您找到了一个可行的解决方案,并且使用重大更改框架似乎可以为您节省一些电池寿命,只要它对您的目的足够准确。您的解决方案也是有益的,因为它允许您通过仅监控您最接近的区域来处理可能超过允许同时监控 20 个区域的每个应用程序限制。

我需要类似的功能,但认为重大更改对于我的应用程序来说不够准确,因此我挖掘了更多内容并找到了以下内容。

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

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

还有在“处理区域的跨界事件”中:

每次用户的当前位置跨越边界区域时,系统都会为您的应用生成适当的区域事件。如果您的应用程序已经在运行,这些事件将直接发送给任何当前位置管理器对象的委托。如果您的应用程序没有运行,系统会在后台启动它,以便它可以响应。应用程序可以实现以下方法来处理越界:

locationManager:didEnterRegion:

locationManager:didExitRegion:

就我而言,我只需要在越界时触发通知,因此我将 AppDelegate 设置为符合 CLLocationManagerDelegate,创建了一个 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];
}

测试表明这无需设置 UIBackgroundModes 位置键即可工作。在这个用例中,操作系统会为您处理边界监控,然后将事件发送到您的应用程序,时间足以处理事件。这不会启动应用程序,它只是在后台运行它几秒钟以处理边界事件,在此期间您只能进行相关活动。希望这对其他人也有帮助!

于 2013-05-03T15:30:58.633 回答
4

是的,它的行为方式相同,只是它会更频繁地接收更新(因此会消耗更多电池)。

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

编辑重新阅读后,似乎程序将从暂停状态中唤醒,而不是终止状态。不过,我不认为你真的需要这种后台模式。它专为需要精细位置信息的应用程序(如逐向导航)而设计。查看位置编程指南中有关“基于区域”编程的部分。您评论中的示例被列为此应用程序的用途之一。

再次编辑根据评论中的讨论,最终的解决方案似乎是设置显着的位置更改,直到用户足够近,然后切换到精细的位置更改(并希望应用程序在此期间不会终止^^ )

于 2012-09-03T01:26:11.103 回答
4

杀死应用程序后,位置更新将发送到应用程序

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

您需要通过查找启动密钥来收集此委托方法中的位置更新,如下所示,

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

希望这就是你要找的。是的,您需要在 plist 中设置键“所需的后台模式”,其值为“应用程序注册以进行位置更新”。

于 2013-08-30T15:59:34.850 回答