进入受监控的信标区域后开始位置更新 Swift

Starting locations updates after enter beacon region monitored Swift

我正在制作一个 ibeacon 区域监控应用程序,当用户进入该区域时(应用程序不在前台)会更新位置。这个位置更新必须配置为 kCLLocationAccuracyBestForNavigation accuracy(因为我必须在使用保持在区域时进行跟踪, 订阅我的重大变化是不够的)。一切正常,但 20 秒后(有时 1 分钟或更长时间)我停止接收位置更新。我将所有键都放在 info.plist 中以始终使用位置,我在功能部分中包含后台模式,并在后台更新位置。

我用不同的配置配置 locationManager,SO 总是停止我的位置更新。我正在使用 IOS 12 和 Iphone 7 进行测试。

我配置CLLocationManager的方式:

self.locationManager.desiredAccuracy
=kCLLocationAccuracyBestForNavigation
self.locationManager.activityType = .automotiveNavigation
self.locationManager.distanceFilter = kCLDistanceFilterNone;
self.locationManager.delegate = self
self.locationManager.allowsBackgroundLocationUpdates = true
self.locationManager.pausesLocationUpdatesAutomatically = false

开始位置更新(当用户进入 Ibeacon 区域时):

func beaconManager(_ manager: KTKBeaconManager, didEnter region: 
KTKBeaconRegion) {



    self.locationManager.startUpdatingLocation()


}

最后,在我调用网络服务的 didUpdate 位置:

func locationManager(_ manager: CLLocationManager, 
didUpdateLocations locations: [CLLocation]) {

    //Call web service using alamofire

}

我请求你的帮助,以了解我是否为我想要执行的目的正确地执行了设置,以及让我知道为什么操作系统终止我的进程以获取位置更新的任何线索

在 iOS 上在后台获取定期位置更新很棘手。操作系统旨在防止应用程序不断 运行 在后台运行以优化电池使用,并且它会在一段时间后暂停它们,除非你有几项完全正确。

你需要做三件事:

  1. 您必须始终获得用户的位置许可(正如您所说的那样)。

  2. 您必须将以下条目添加到您的 Info.plist。这将允许您的应用程序无限期地在后台 运行,但是如果您希望将您的应用程序提交到 App Store,此条目还将向审阅者声明它是一个后台定位应用程序,您需要说服他们知道它为用户提供了 location-based 好处,并且用户知道这种好处。

 <key>UIBackgroundModes</key>
 <array>
     <string>location</string>
 </array>
  1. 您必须维护一个后台线程以保持您的应用程序处于活动状态。您是否真的在此后台线程中执行任何操作都没有关系。只要让它处于活动状态,iOS 就不会暂停您的应用程序。
  var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskIdentifier.invalid

  func extendBackgroundRunningTime() {
    if (backgroundTask != UIBackgroundTaskIdentifier.invalid) {
      // already started
      return
    }
    NSLog("Attempting to extend background running time")

    self.backgroundTask = UIApplication.shared.beginBackgroundTask(withName: "DummyTask", expirationHandler: {
      NSLog("Background task expired by iOS.  Cannot run again until a new beacon region event")
      UIApplication.shared.endBackgroundTask(self.backgroundTask)
      self.backgroundTask = UIBackgroundTaskIdentifier.invalid
    })

    DispatchQueue.global().async {
      while (true) {
        let backgroundTimeRemaining = UIApplication.shared.backgroundTimeRemaining
        // This will be a very large number if you have proper permissions
        // If not, it will generally count down from 10 seconds once you are in the
        // background until iOS suspends your app.
        NSLog("Thread background time remaining: \(backgroundTimeRemaining)")
        Thread.sleep(forTimeInterval: 1.0)
      }
    }
  }