2015-01-13 109 views
0

我写了一个应用程序的监视器用户的位置。位置服务在我的视图加载时打开:IOS:当应用程序在后台停止位置更新一段时间

// Create the location manager if this object does not 
// already have one. 
if (nil == self.locationManager) { 
    self.locationManager = [[CLLocationManager alloc] init]; 
} 

self.locationManager.delegate = self; 

// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7. 
if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { 
    [self.locationManager requestAlwaysAuthorization]; 
} 

[self.locationManager startMonitoringSignificantLocationChanges]; 
NSLog(@"Started monitoring significant location changes"); 

如果我终止应用程序,而其活动位置服务停止。这是我写的AppDelegate.m停止位置服务的代码:

- (void)applicationWillTerminate:(UIApplication *)application { 
    // Called when the application is about to terminate. Save data if appropriate. See also    
     applicationDidEnterBackground:. 
    // Saves changes in the application's managed object context before the application terminates. 
    NSLog(@"entered terminate in delegate"); 
    [myController.locationManager stopUpdatingLocation]; 
    [myController.locationManager stopMonitoringSignificantLocationChanges]; 
    myController.locationManager = nil; 
    [self saveContext]; 
} 

我遇到了这样的问题:如果我的应用程序已经在后台,上述方法不调用,因此我无法关闭位置服务。要解决这个问题,我发现这个解决方案,我想:

- (void)applicationDidEnterBackground:(UIApplication *)application { 
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 

    UIApplication *app = [UIApplication sharedApplication]; 
    if ([app respondsToSelector:@selector(beginBackgroundTaskWithExpirationHandler:)]) { 
     self.bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
      // Synchronize the cleanup call on the main thread in case 
      // the task actually finishes at around the same time. 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       if (self.bgTask != UIBackgroundTaskInvalid) 
       { 
        NSLog(@"Marking bgTask as Invalid when we entered background"); 
        [app endBackgroundTask:self.bgTask]; 
        self.bgTask = UIBackgroundTaskInvalid; 
       } 
      }); 
     }]; 
    } 
} 

所以上述方案工作,如果我的应用程序是在后台。但是,我注意到,如果让我的应用程序长时间在后台运行超过五分钟,过期处理程序就会启动。因此,如果我终止应用程序而不将它带到前台。位置服务图标仍会显示在手机上。我必须重新启动应用程序或将其带到前台先终止它禁用定位服务踢代码

如果我删除这两条线:

  [app endBackgroundTask:self.bgTask]; 
     self.bgTask = UIBackgroundTaskInvalid; 

然后停止位置服务工程在调试器连接五分钟后找到。如果我让它在后台运行时间更长,那么终止代码从不会启动。是因为我没有更改位置或应用程序最终死亡?

所以我的问题是,是否有另一种方式来确保应用程序正确停止位置服务监控,如果它在后台一段时间?

谢谢...荷银


编辑,我做更多的实验,这里是我的发现:

当连接到调试器,如果我等待11分钟不时进入后台模式,该方法willTerminate被调用:

2015-01-13 08:52:45.935 [441:37074] @@@AMRO--->applicationWillResignActive entered 

2015-01-13 08:52:46.642 [441:37074] @@@AMRO--->Entered background mode 

2015-01-13 08:55:42.697 [441:37074] @@@AMRO--->beginBackgroundTaskWithExpirationHandler called 

2015-01-13 09:03:26.265 [441:37074] entered terminate in delegate 

如果我试试这个没有调试器,只能等待4分,终止函数不会被调用,我不必等待WH ole 11分钟。

+0

看看这个帖子http://stackoverflow.com/questions/24778492/stop-location-updates-when-app-terminate/24778607#24778607,听起来像一个类似的问题,还有,你打开位置更新背景模式? –

+0

@GuyS是的我需要在后台模式下进行位置跟踪。根据我的问题和实现细节,如果后台应用程序在后台运行超过5分钟,则您提供的堆栈溢出链接解决方案不起作用 –

+0

您确定它是5分钟而不是3分钟吗?在iOS 7后台任务3分钟后停止,我不知道它是否改变了ios 8(我不这么认为)。无论如何,我用这个帖子http://stackoverflow.com/questions/18901583/start-location-manager-in-ios-7-from-background-task获取位置更新在后台,我只是检查,它的位置现在在后台更新20分钟...只需确保添加requestAlwaysAuthorization和plist字符串NSLocationAlwaysUsageDescription。 希望这有助于 –

回答

2

从苹果的文档:

应用程序终止

应用程序必须准备终止在任何时间发生,应该 迫不及待地保存用户数据或执行其它关键任务。 系统启动的终止是应用程序生命周期的正常组成部分。 系统通常会终止应用程序,以便它可以回收内存,并且 为用户启动的其他应用程序腾出空间,但系统 也可能会终止行为不当或未及时响应 事件的应用程序。

暂停的应用接收的时候都没有终止通知;系统会杀死进程并回收相应的内存。如果 应用程序正在后台运行,而不是暂停时, 系统调用applicationWillTerminate:它的应用程序委托之前 终止。当设备 重新启动时,系统不会调用此方法。

除了系统终止您的应用程序,用户可以明确使用多任务UI来终止 您的应用程序。用户启动的 终止与终止暂停的应用具有相同的效果。 应用程序的进程被终止并且没有通知被发送到应用程序。

https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html#//apple_ref/doc/uid/TP40007072-CH2-SW1

关于significantChangesLocation:

如果离开了显著变化位置服务运行,您 iOS应用随后被暂停或终止,服务 自动唤醒你的应用程序时新的位置数据到达。

https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html

如果您不希望您的应用程序通过significantChangeLocation唤醒你,你可以调用stopMonitoringSignificantLocationChanges时backgroundTimeRemaining即将到期。

Att。

+0

感谢您的回复,从我的测试中,这是我收集的。我把我的应用程序用于驱动器。把它放在后台,每次触发位置更新时,我都会发出通知,以便在UI中看到它。所以这证明即使应用程序被暂停,我仍然收到通知。这在位置更新方面很好,但如果位置指针始终保持不变,用户将会感到不安。我想我将不得不通过使用backgroundExpirationHandler和定时器组合来停止和启动位置服务来解决此问题 –

相关问题