vin*_*h87 1 background core-location cllocationmanager ios swift
我创建了一个位置跟踪 ios 应用程序(使用 CocoaLumberjack 库写入日志文件)。因此启用了后台位置更新并用于我的测试(我几乎在后台运行了 8 小时)。当应用程序进入实时商店时。我们的应用程序中发生了很多问题。当应用程序转到后台位置跟踪无法正常工作时。它不会在一段时间内将用户位置发送到服务器。所以我从客户端获取日志文件并查看日志文件中是否存在时间间隔。我经常获取用户位置(每隔一秒)。所以我认为应用程序在日志文件中出现间隙时进入暂停状态?为什么即使我经常在后台获取位置,应用程序也会进入暂停状态?应用程序是否有理由进入暂停状态?搜索了很多找不到任何有效的详细信息?
func startTimer()
{
if bgTimer == nil
{
bgTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.startLocationChanges), userInfo: nil, repeats: true)
}
}
func stopTimer()
{
if bgTimer != nil
{
bgTimer?.invalidate()
bgTimer = nil
}
}
@objc func startLocationChanges() {
locationManager.delegate = self
locationManager.allowsBackgroundLocationUpdates = true
locationManager.pausesLocationUpdatesAutomatically = false
locationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//let lastLocation = locations.last!
// Do something with the location.
/*print(lastLocation)
let logInfo = "BGLocationManager didUpdateLocations : " + "\(lastLocation)"
AppDelegate.appDelegate().writeLoggerStatement(strInfo: logInfo)*/
locationManager.stopUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
if let error = error as? CLError, error.code == .denied {
// Location updates are not authorized.
manager.stopMonitoringSignificantLocationChanges()
return
}
// Notify the user of any errors.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// 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 applicationDidEnterBackground: when the user quits.
self.writeLoggerStatement(strInfo: "applicationDidEnterBackground")
appstate = "Background"
if CoreDataUtils.isUserLoggedIn(entityName: "UserInfo") == true {
let user = CoreDataUtils.fetchCurrentUser(entityName: "UserInfo")
if user!.isGPSActive == "1"
{
if backgroundTaskIdentifier != nil
{
application.endBackgroundTask(backgroundTaskIdentifier!)
backgroundTaskIdentifier = UIBackgroundTaskInvalid
}
backgroundTaskIdentifier = application.beginBackgroundTask(expirationHandler: {
//UIApplication.shared.endBackgroundTask(self.backgroundTaskIdentifier!)
})
BGLocationManager.shared.startTimer()
let logInfo = String(format:"applicationDidEnterBackground backgroundTimeRemaining : %f",(Double)(application.backgroundTimeRemaining / 60))
self.writeLoggerStatement(strInfo: logInfo)
}
}
}
Run Code Online (Sandbox Code Playgroud)
一些观察:
该beginBackgroundTask只买你30秒没有8小时。(在 13 之前的 iOS 版本中,这是 3 分钟,而不是 30 秒,但这一点仍然成立。)底线,这旨在让您完成一些简短的、有限长度的任务,而不是让应用无限期地运行。更糟糕的是,如果你不调用endBackgroundTask它的完成处理程序,当分配的时间到期时,应用程序将被毫不客气地终止。
后台位置更新有两种基本模式。
在测试这些类型的后台交互时,您不希望附加到 Xcode 调试器。通过调试器运行它实际上改变了应用程序的生命周期,防止它永远挂起。
由于通常不会让应用无限期地在后台运行,这意味着您需要删除Timer相关代码。