ios - 我的应用程序进入暂停状态的原因是什么?

标签 ios swift background core-location cllocationmanager

我创建了一个位置跟踪 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)
        }
    }
}

最佳答案

一些观察:

  1. beginBackgroundTask 只为您争取 30 秒,而不是 8 小时。 (在 iOS 13 之前的版本中,这是 3 分钟,而不是 30 秒,但这一点仍然成立。)最重要的是,这旨在让您完成一些短的、有限长度的任务,而不是让应用程序无限期地运行。更糟糕的是,如果您不在其完成处理程序中调用 endBackgroundTask,则该应用将在分配的时间到期时被粗暴地终止。

  2. 后台位置更新有两种基本模式。

    • 如果该应用是导航应用,那么您可以让该应用在后台运行。但是让标准定位服务在后台运行会在几个小时内耗尽用户的电量。因此,Apple 只会在您的应用绝对需要时才授权这样做(例如,您的应用是一个真正的导航应用,而不仅仅是一个出于其他原因而恰好想要跟踪位置的应用)。

    • 另一个模式是significant change service .使用此服务,您的应用程序将被暂停,但操作系统会唤醒它以提供位置更新,然后让它再次暂停。参见 Handling Location Events in the Background .这不像标准定位服务那样精确,但由于该应用不是持续运行的,而且它不需要启动 GPS 硬件,因此它消耗的电量要少得多。

  3. 在测试这些类型的后台交互时,您不希望依赖于 Xcode 调试器。通过调试器运行它实际上会改变应用的生命周期,防止它永远挂起。

  4. 由于人们通常不会无限期地让应用程序在后台运行,这意味着您需要删除与 Timer 相关的代码。

关于ios - 我的应用程序进入暂停状态的原因是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58360650/

相关文章:

ios - Swift 应用程序终止会删除 Kingfisher 磁盘缓存

css - 使用草图作为背景的processing.js

ios - 在不同的设备方向上更改 UICollectionViewCell 大小

ios - SpriteKit,把一个进程放在另一个核心上?

swift - 符合 'CBCentralManagerDelegate'协议(protocol)

android - setBackgroundResource 和 setBackgroundDrawable 有什么区别

css - 灯箱:使屏幕其余部分透明的问题

objective-c - 自定义 UITextField 清除按钮

ios - 使用 UIActivityViewController 自定义打印

json - 如何使用 swift 4 解码这个 JSON