在后台调用时,CLLocationManager startUpdatingLocation()不起作用

我有一个特定的用例,我希望能够在应用程序已经在后台时开始位置更新。 具体来说,我希望能够按下我的Pebble watchapp上的button,并导致我的伴侣iOS应用程序开始位置更新。

只有iOS应用程序处于前台或在过去的几秒钟内刚刚进入后台(如5?),我才能够成功地从我的Pebble启动位置更新。 几秒钟后,应用程序在后台,我不能再启动更新。 我知道更新还没有开始,因为backgroundTimeRemaining开始倒数到0(如果更新开始,它保持在最大值)。 我还在顶部显示位置更新(“_____正在使用您的位置”)时显示的蓝色条,并且在经过了这个奇怪的〜5秒的阈值之后也没有出现。

我已经看过几乎所有关于SO的相关问题,而且我已经基本上尝试了所有build议的内容,例如在开始位置更新之前开始后台任务。 我也尝试了在开始后台任务后几秒钟延迟位置更新的开始,这也不起作用。

奇怪的是,我也有一个苹果手表的应用程序,做Pebble应用程序相同的东西,苹果手表能够始终开始位置更新而不失败。 也许苹果手表可以做一些特殊的地方取消iOS应用程序?

这是在iOS 9上。

任何forms的帮助表示赞赏,我会尝试任何build议。

更新:我把一个快速示例应用程序,演示了这个问题。 该代码张贴在下面,或者你可以从GitHub下载项目: https : //github.com/JessicaYeh/BackgroundLocationTest

如果你尝试一下,你可以看到延迟设置为2秒,但延迟时间较长(如10秒),更新不会启动。

// // AppDelegate.swift // BackgroundLocationTest // // Created by Jessica Yeh on 2/18/16. // Copyright © 2016 Yeh. All rights reserved. // import UIKit import CoreLocation @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? let locationManager = CLLocationManager() var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid var timer: NSTimer? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { debugPrint(__FUNCTION__) // Setup location manager locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.requestWhenInUseAuthorization() locationManager.allowsBackgroundLocationUpdates = true return true } @objc func checkBackgroundTimeRemaining() { debugPrint(UIApplication.sharedApplication().backgroundTimeRemaining) } @objc func endBackgroundTask() { if self.backgroundTask != UIBackgroundTaskInvalid { UIApplication.sharedApplication().endBackgroundTask(self.backgroundTask) self.backgroundTask = UIBackgroundTaskInvalid } } func applicationWillResignActive(application: UIApplication) { debugPrint(__FUNCTION__) } func applicationDidEnterBackground(application: UIApplication) { debugPrint(__FUNCTION__) // Cancel old timer and background task timer?.invalidate() endBackgroundTask() // Start a new background task backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler { self.endBackgroundTask() } // Start updating location // let delaySec = 2.0 // successfully starts location update let delaySec = 10.0 // doesn't start location update let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delaySec * Double(NSEC_PER_SEC))) dispatch_after(delayTime, dispatch_get_main_queue(), { debugPrint("Attempting to start updating location") self.locationManager.startUpdatingLocation() }) // Keep checking every 3 sec how much background time app has left timer = NSTimer.scheduledTimerWithTimeInterval(3.0, target: self, selector: Selector("checkBackgroundTimeRemaining"), userInfo: nil, repeats: true) } func applicationWillEnterForeground(application: UIApplication) { debugPrint(__FUNCTION__) } func applicationDidBecomeActive(application: UIApplication) { debugPrint(__FUNCTION__) } func applicationWillTerminate(application: UIApplication) { debugPrint(__FUNCTION__) } } extension AppDelegate: CLLocationManagerDelegate { func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { debugPrint(__FUNCTION__) } } 

那么,我不完全是你所尝试的,但要确保你已经打开目标的function(能力 – >背景模式)的位置更新,而且对于iOS 9.0,添加:

 if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"9.0")) { self.locationManager.allowsBackgroundLocationUpdates = YES; } 

并改变行:

 locationManager.requestWhenInUseAuthorization() 

至:

 locationManager.requestAlwaysAuthorization(). 

祝你好运!