当用户打开定位服务时收到通知 iOS 7 及以上

Being notified when user turns on location services iOS 7 and up

我遇到这样一种情况,我们希望根据用户是否启用位置服务来启动特定流程。这部分是微不足道的。但是,如果用户关闭或打开位置服务,我们希望通过更改我们的流程来扩展此功能。当用户关闭位置服务时,我们目前能够监控、更改或处理。我的问题是,当用户重新打开位置服务时,如何通知我们的应用程序?

这是我们目前正在处理的内容

这是我们尝试过的

  1. 我们已经尝试在用户关闭定位服务后设置一个定时器,以定期检查用户是否重新打开定位服务。由于许多原因,这是不太理想的。除此之外,一旦位置服务关闭,定时器就会被终止,因为不再需要后台服务并且 OS 会终止我们的进程。这是可以理解的。
  2. 我们还采用了通知用户他们刚刚停止了一个进程并且需要重新打开定位服务的方法。这种方法有两个问题。
    1. 如果用户没有启用通知,那么这种方法根本就不好。
    2. 如果他们确实启用了通知,那么我们首先需要用户重新打开定位服务,然后他们需要重新打开应用程序以使我们的应用程序 "wake" 备份。

提前致谢!

经过数小时的研究和尝试解决方案,我们发现从 iOS 8 开始这是不可能的。我们发现以下内容供参考:

  1. 我们能够在用户关闭定位服务时收到通知,如果他们关闭了我们应用程序的定位服务。如果用户关闭主要位置服务,我们不会收到通知。
  2. 如果位置服务重新打开,我们不会收到消息,无论是我们的位置服务还是主要位置服务。
  3. 您不能使用计时器方法,因为如果将应用程序发送到后台,计时器将被终止。所以我们不能定期检查。 这对于我们的用例来说是不可接受的,但值得娱乐
  4. 您仍然可以调用 CLLocationManager,就像您有权使用定位服务一样,即使您没有权限。
  5. 如果您调用 CLLocationManager,您将开始接收位置消息,在您的应用获得权限后,无需重新注册即可接收位置消息。


我们的解决方案:

4 和 5 的组合是我们的救星。我们遇到了一个边缘案例,用户可能有资格触发位置事件,但之前拒绝使用位置服务,然后在符合条件后,用户授予我们使用位置服务的权限。在做了一些重构之后,我们移动了我们的位置管理器,这样我们就可以注册位置事件更新,特别是地理围栏,即使我们没有权限。经过测试,我们发现在边缘案例事件中,我们甚至无需重新初始化位置管理器就可以开始接收位置更新。这同样适用于任何感兴趣的人的信标区域监控。

请在应用进入前台后检查您的定位服务。

  NotificationCenter.default.addObserver(self, selector: #selector(applicationDidEnterForeground), name: UIApplication.didEnterForegroundNotification, object: nil)

  func applicationDidEnterForeground() {
    print("Location services enabled? \(CLLocationManager.locationServicesEnabled())")
  }