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

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

我明白,苹果允许后台任务只有三分钟。 我的应用程序更像是一个跟踪应用程序,即使应用程序在后台,也能跟踪用户的位置,所以我需要实现此function。

我了解到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中的定期位置更新有点棘手。有一个很好的线程讨论这个,你可以在这里阅读更多

无论您的计时器是否正在运行,iOS会在几分钟后终止您的应用程序。 有一种解决方法,虽然我写了一个离子应用程序时,我不得不做类似的事情,所以你可以看看这里的代码,这个链接有一个快速的类,pipe理定期更新的iOs。

为了在背景中获得定期的位置,而不是耗尽设备的电池,您需要发挥位置logging的准确性,降低位置pipe理器将其所需准确度设置为kCLLocationAccuracyThreeKilometers的精度,然后,每60秒钟需要将精度更改为kCLLocationAccuracyBest,这将使代表得到一个新的,准确的位置更新,然后将精度恢复到低。 计时器每次收到更新时都需要进行初始化。

还有一种方法可以在用户杀死后台的时候唤醒应用程序,使用应用程序委托让应用程序在死亡之前监听位置的重大变化。 当用户的位置跳得很大(可能在200ms左右)时,会在后台唤醒应用程序。 应用程序唤醒时,停止监视重大更改并像往常一样重新启动位置服务,以继续定期更新。

希望这可以帮助。

更新

在Swift 2中,你还需要:

 self.locationManager.allowsBackgroundLocationUpdates = true 

您可以使用库进行背景位置跟踪 ,例如使用:

  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 } 

当应用程序被终止或暂停时,它正在工作。