【问题标题】:Run a Swift 2.0 app forever in background to update location to server永远在后台运行 Swift 2.0 应用程序以将位置更新到服务器
【发布时间】:2016-07-08 23:56:52
【问题描述】:

我编写了下面的代码,它有一个每分钟调用一个回调函数的计时器。当应用程序进入后台时,我启动了另一个调用相同回调方法的计时器,但后台计时器只工作了三分钟。

我了解 Apple 只允许后台任务执行三分钟。我的应用更像是一个跟踪应用,即使应用在后台,也会每分钟跟踪用户的位置,所以我需要实现这个功能。

得知要使用beginBackgroundTaskWithExpirationHandler,但不知道我的实现是否正确。

注意:我在 plist toApp 寄存器中有必需的后台模式以进行位置更新。

非常感谢任何有效的代码或链接。

override func viewDidLoad() {
    super.viewDidLoad()

    timeInMinutes = 1 * 60

    self.locationManager.requestAlwaysAuthorization()

    self.locationManager.requestWhenInUseAuthorization()

    if CLLocationManager.locationServicesEnabled() {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        locationManager.startUpdatingLocation()
    }

    var timer = NSTimer.scheduledTimerWithTimeInterval( timeInMinutes, target: self, selector: "updateLocation", userInfo: nil, repeats: true)
}

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){
    let locValue:CLLocationCoordinate2D = manager.location!.coordinate

    self.latitude = locValue.latitude
    self.longitude = locValue.longitude

    if UIApplication.sharedApplication().applicationState == .Active {

    } else {
        backgroundTaskIdentifier = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({ () -> Void in
            self.backgroundTimer.invalidate()
            self.backgroundTimer = NSTimer.scheduledTimerWithTimeInterval( 60.0, target: self, selector: "updateLocation", userInfo: nil, repeats: true)
        })
    }
}

func updateLocation() {
    txtlocationLabel.text = String(n)
    self.n = self.n+1

    var timeRemaining = UIApplication.sharedApplication().backgroundTimeRemaining

    print(timeRemaining)

    if timeRemaining > 60.0 {
        self.GeoLogLocation(self.latitude,Longitude: self.longitude) {
            results in
            print("View Controller: \(results)")
            self.CheckResult(String(results))
        }
    } else {
        if timeRemaining == 0 {
            UIApplication.sharedApplication().endBackgroundTask(backgroundTaskIdentifier)
        }

        backgroundTaskIdentifier2 = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({ () -> Void in
            self.backgroundTimer.invalidate()
            self.backgroundTimer = NSTimer.scheduledTimerWithTimeInterval( 60.0, target: self, selector: "updateLocation", userInfo: nil, repeats: true)
        })
    }
}

【问题讨论】:

    标签: ios iphone swift background core-location


    【解决方案1】:

    您可以使用background location tracking的库,使用示例:

        var backgroundLocationManager = BackgroundLocationManager()
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
    
         backgroundLocationManager.startBackground() { result in
                if case let .Success(location) = result {
                    LocationLogger().writeLocationToFile(location: location)
                }
        }
    
        return true
    }
    

    它在应用程序被杀死或挂起时工作。

    【讨论】:

      【解决方案2】:

      IOS 中的定期位置更新有点棘手。有一个很好的线程讨论了这个,你可以阅读更多here

      无论您的计时器是否正在运行,iOS 都会在几分钟后终止您的应用。不过有一种方法可以解决这个问题,我在编写 ionic 应用程序时必须做类似的事情,这样你就可以查看这个 here 的代码,该链接有一个 swift 类,用于管理 iO 中的定期位置更新。

      为了在后台获取周期性位置,并且不耗尽设备的电池,您需要使用位置记录的准确性,降低位置管理器的准确性,将其 desiredAccuracy 设置为 kCLLocationAccuracyThreeKilometers,然后,每个您需要在 60 秒内将准确度更改为 kCLLocationAccuracyBest,这将使代理能够获得新的准确位置更新,然后将准确度恢复为低。每次收到更新时都需要初始化计时器。

      还有一种方法可以在应用被用户杀死后在后台唤醒它,使用应用委托让应用在被杀死之前监听位置的重大变化。当用户的位置发生很大的跳跃(可能是 200 毫秒左右)时,这将在后台唤醒应用程序。当应用唤醒时,停止监控重大变化并像往常一样重新启动位置服务以继续定期更新。

      希望这会有所帮助。

      更新

      在 Swift 2 中,您还需要:

      self.locationManager.allowsBackgroundLocationUpdates = true
      

      【讨论】:

      • 感谢您的帮助...我对 Swift 很陌生...我尝试按照您所说的每 60 秒更改一次准确度值...我仍然得到相同的结果(即应用程序运行并且在后台运行后仅更新位置三分钟)
      • 您好,对不起,我忘了提,而且我相信您的代码中缺少这一点,您还需要在位置管理器中启用后台位置,类似于 self.locationManager.allowsBackgroundLocationUpdates = true
      • 没问题!很乐意为您提供帮助。
      • 在我的情况下,使用 iOS 10,在应用程序被用户杀死后唤醒应用程序的功能不再起作用。我已经启动并运行了@DanielOrmeño 的代码。然而,自从更新后,一个重大的位置变化会重新启动应用程序,但它会在三分钟后再次被杀死。谁能证实这一点?还有其他解决方法吗?
      • 你好@mikey,我已经有一段时间没碰这个了,但是在快速搜索之后,我在iOS10中找不到任何重大变化,如果应用程序被杀死,可能是因为你的间隔时间用于更新的时间太长,Apple 允许您添加一个标志来要求操作系统有更多时间来完成任务。请参阅developer.apple.com/library/content/documentation/iPhone/… 中的“实现长时间运行的任务”,希望这会有所帮助
      猜你喜欢
      • 2020-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多