重大更改位置API在终止/暂停时的行为?

这是CLLocationManager文档中用startMonitoringSignificantLocationChanges描述应用行为的部分 :

如果您启动此服务,并且您的应用程序随后终止,则系统会在新事件到达时自动将应用程序重新启动到后台。 在这种情况下,传递给应用程序委托的应用程序:didFinishLaunchingWithOptions:方法的选项字典包含UIApplicationLaunchOptionsLocationKey键,以指示您的应用程序是由于位置事件而启动的。 重新启动后,您仍然必须configuration位置pipe理器对象,并调用此方法继续接收位置事件。 当您重新启动位置服务时,当前事件会立即传送到您的委托。 另外,即使在启动位置服务之前,您的位置pipe理器对象的位置属性也会填入最近的位置对象。

所以我的理解是,如果你的应用程序终止(我假设如果你不从applicationWillTerminate调用stopMonitoringSignificantLocationChanges ),你会被唤醒一个UIApplicationLaunchOptionsLocationKey参数应用程序:didFinishLaunchingWithOptions 。 在这一点上,你创build你的CLLocationManager ,调用startMonitoringSignificantLocationChanges并在有限的时间内做你的后台定位处理。 所以我很好,这一点。

前面的段落只是说明应用程序终止时会发生什么,而不会提示应用程序暂停时的操作。 didFinishLaunchingWithOptions的文档说:

应用程序在后台跟踪位置更新,被清除,现在已经重新启动。 在这种情况下,字典中包含一个键,指示应用程序由于新的位置事件而重新启动。

build议您只有在您的应用程序启动后(由于位置更改)才会收到此通知。

然而, 位置感知编程指南中 重要变更服务的段落如下:

如果您退出此服务并且您的应用程序随后被暂停或终止,则服务会在新的位置数据到达时自动唤醒您的应用程序。 在起床时,您的应用程序将被放入后台,并给予less量时间来处理位置数据。 因为你的应用程序在后台,所以它应该做最less的工作,并避免任何可能阻止它在分配的时间到期之前返回的任务(例如查询networking)。 如果没有,您的申请可能会被终止。

这表明,如果您的应用已被暂停,您将被位置数据唤醒,但未能提及您是如何被唤醒的:

  • UIApplicationDelegate是否得到一个callback告诉我,我正在从挂起状态恢复到后台状态?
  • 位置pipe理器(当应用程序被暂停时被冻结)开始接收locationManager:didUpdateToLocation:fromLocationcallback?
  • 我是否只需要在我的didUpdateToLocation消息中实现代码来检查应用程序状态,并在后台模式下进行最less的处理?

在写这篇文章的过程中,我想我可能只是回答了我自己的问题,但如果我对这个问题有更深入的了解,我的理解会很棒。

自从我问这个问题以来,我做了一些testing(主要是在家庭和工作之间的火车上),并且已经证实暂停应用程序的行为正如我在问题结束时所怀疑的那样。

也就是说,您的被暂停的应用程序被唤醒,您没有收到您的应用程序委托的任何callback,而是通过现有的CLLocationManagerDelegate接收您的位置更新。 您可以通过检查applicationState来检测到您正在运行后台,并且对于从暂停状态中唤醒以进行位置处理的情况,可以进行有限的工作。

[UIApplication sharedApplication].applicationState == UIApplicationStateBackground 

我用一个位置testing工具来得出这个结论,欢迎您下载并尝试。 这是一个非常简单的应用程序,允许您通过UI打开重大更改和gps更改API,并logging您找回的所有响应。

NB在前面的答案中的六点是不正确的。 冻结已中止的应用程序在从挂起状态唤醒时会收到CLLocationManagerDelegatecallback。

我的理解如下(我正在编写依赖于此API的应用程序,但尚未完成此组件足以开始testing):

  1. 您的应用程序是第一次运行,您注册启动监视重要位置更改 ,并提供callback函数。 当您的应用程序正在运行时,只要收到重大更改,就会调用该callback。
  2. 如果您的应用程序被置于后台,UIApplication将接收applicationWillResignActive ,然后是applicationDidEnterBackground
  3. 如果您的应用程序在后台暂停时被杀害,您将不会收到通知; 然而,如果您的应用程序在运行时被终止(根据我的知识,前景或背景),您将得到一个applicationWillTerminate的时刻。 您不能从这个function请求额外的背景时间。
  4. 尽pipe在后台遇难,操作系统将重新启动您的应用程序。 如果您的应用程序是由操作系统简单地启动以进行更改,则会调用应用程序didFinishLaunchingWithOptions

     if ([launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey]) 

    将帮助您确定您是否从背景位置更改回来。

  5. 如果您目前正在后台运行,并且您的应用程序由用户手动重新启动,则您将收到applicationWidEnterForeground,接着是applicationDidBecomeActive
  6. 无论如何发生,当您的应用程序重新启动(除非由于后台任务仍然在后台运行,并且说任务已经开始监视更改),则需要明确告诉它再次启动监视重要位置更改,因为callback是否“冻干”后附着时间较长。 是的,你只需要在didUpdateToLocation中实现代码,一旦你从挂起状态返回,重新连接了某种位置处理程序。

这就是我现在正在进行的代码开发。 正如我之前提到的,我还没准备好在设备上进行testing,因此我无法确定是否正确解释了所有内容,因此请评论者随时纠正我的错误(尽pipe我已经在话题)。

哦,如果由于运气不好,你发布了一个应用程序,做我想要做的事,我可能会哭:)

祝你好运!

如果应用程序由于位置更改而从暂停状态中唤醒,则应用程序将以后台状态启动。

所有的对象将会实时生效,您将在现有的代理中接收位置更新。