一尘不染

永远在后台运行Swift 2.0应用程序以更新服务器位置

swift

我写了下面的代码,其中包含一个计时器,每分钟调用一次回调函数。当应用程序进入后台时,我已经启动了另一个计时器,该计时器调用相同的回调方法,但是后台计时器仅工作三分钟。

我了解到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)
        })
    }
}

阅读 276

收藏
2020-07-07

共1个答案

一尘不染

定期的位置更新在IOS中有点棘手,有一个很好的讨论这个话题,您可以在这里阅读更多内容

无论您的计时器是否在运行,iOS都会在几分钟后终止您的应用程序。不过,有一种解决方法,我在编写离子应用程序时必须做类似的事情,因此您可以在此处查看代码,该链接具有一个快速类,用于管理iO中的定期位置更新。

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

还有一种方法可以在用户杀死应用程序之后在后台唤醒该应用程序,使用应用程序委托让该应用程序在其被杀死之前侦听位置的重大变化。当用户的位置发生较大变化(大约200毫秒)时,这会在后台唤醒应用。当应用程序唤醒时,请停止监视重大更改,并照常重启位置服务以继续进行定期更新。

希望这可以帮助。

更新资料

在Swift 2中,您还需要:

self.locationManager.allowsBackgroundLocationUpdates = true
2020-07-07