【发布时间】:2020-02-06 10:54:07
【问题描述】:
我目前正在 iOS 13 中测试后台定位模式,因为我想在后台跟踪用户的位置和运动(使用 CMMotionManager)。 因此,我有自己的(单例)类来处理位置跟踪。我通过以下方式初始化 CLLocationManager:
func initializeLocationManager() -> CLLocationManager {
let manager = locationManager ?? CLLocationManager()
manager.delegate = self
manager.requestAlwaysAuthorization()
manager.allowsBackgroundLocationUpdates = true
manager.pausesLocationUpdatesAutomatically = false
manager.distanceFilter = kCLDistanceFilterNone
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.activityType = .other
return manager
}
然后我启动以下服务:
func startLocationServices() {
// ...
locationManager.startUpdatingLocation()
locationManager.startMonitoringVisits()
locationManager.startMonitoringSignificantLocationChanges()
// ...
}
另外,我实现了 CLLocationManagerDelegate-methods didChangeAuthorization()、didUpdateLocation()。
在 info.plist 文件中,我附加了以下条目:
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>...</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>...</string>
<key>UIBackgroundModes</key>
<array>
<string>location</string>
</array>
在我的 ViewController 中,我调用了 startLocationServices。 目前,我将应用程序跟踪位置数据的授权设置为“.authorizedAlways”
位置更新会在大约 60 - 130 分钟后停止。
为了解决这个问题,我已经添加了 didFinishLaunchingWithOptions 函数,它会再次触发位置更新:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if let launchOptions = launchOptions,
let isLocationKey = launchOptions[UIApplication.LaunchOptionsKey.location] as? Bool,
isLocationKey {
restartServices()
}
return true
}
当应用程序使用此功能被唤醒时,我设法获得了一些测试的连续数据,但有时应用程序会在几分钟后再次挂起。
最后,我还尝试了一个计时器,它每 5 分钟重新启动一次位置跟踪,但这似乎根本不会影响更新持续时间。
所以我的问题是,是否有办法在后台持续接收位置更新,或者我是否缺少某些选项?
提前致谢。
编辑:我在 iOS 12 上测试了该应用程序,它在 5/5 测试中不断更新。 所以我猜这个问题与 iOS 13 有关。
【问题讨论】:
-
嘿,您找到解决方案了吗?
-
好吧,正如我在上一条评论中所说,通过减少后台消耗的资源,我可以大幅增加应用程序进入挂起状态之前的持续时间。 -> 我从应用程序中完全删除了动作集合。 -> 切换到后台时,我会降低准确性并增加位置的 distanceFilter 以获得更少的事件,我会停止一些更新 UI 的任务,我对其他数据源的集合进行下采样,我不会在后台导出我的数据或其他工作量。所以现在我在后台大约有 3000 分钟。
-
你能帮我写一些代码吗?
-
在您的 AppDelegate.swift 中实现 func applicationDidEnterBackground(_ application: UIApplication) 和 func applicationDidEnterBackground(_ application: UIApplication) 函数。在这些函数中访问您的 CLLocationManager 并相应地设置属性 distanceFilter、desiredAccuracy。我还对用于写入一些使用信息(如当前电池状态)的计时器进行了下采样,并在 applicationDidBecomeActive 方法时结束用于定期更新主视图的计时器,反之亦然。我想玩和测试是关键。
标签: ios swift background cllocationmanager cllocation