IOS延迟的位置更新无法推迟

我正在考虑使用iOS活动跟踪器的延迟位置更新,这允许位置服务在后台。 我已经实现了build议的代码片段(见下文)。 在Xcodedebugging中,延迟位置尝试启动几次,直到位置数据以大约每秒1次的速度进入。 之后,它声称成功启动延迟,并且在指定时间段到期之后,成功触发器的callback也成功。 然而,在此期间,位置处理程序仍然每秒运行一次。 我读过,这是因为手机没有认为自己准备好进入后台,并在Xcodetesting这样做。 请注意,AppDelegate的“didEnterBackground”事件处理程序在closures屏幕时立即被调用,并在重新打开应用程序时恢复。

我使用与另一个testing断开电话相同的代码,在GPS附近窗口附近,屏幕closures或切换到完全不同的应用程序,它仍然从来没有实际推迟更新。 我可以告诉,因为networking更新每30秒钟仍然进入一次,而不是下面的代码示例中所需的120秒间隔。

还有什么需要实际延迟工作,因为没有错误发生在启动他们,他们完成callback? 为什么即使应用程序转到后台,位置更新仍然以每秒1次的速度继续?

Iphone 5s,IOS 7.1.1

// .h file (partial) @interface MotionTracker : NSObject<CLLocationManagerDelegate, UIAccelerometerDelegate> @property (strong, nonatomic) CLLocationManager *locationManager; @end // .m file (parial) - (id) init { if(self = [super init]){ _locationManager = [[CLLocationManager alloc] init]; _locationManager.delegate = self; _locationManager.distanceFilter = kCLDistanceFilterNone; _locationManager.desiredAccuracy = kCLLocationAccuracyBest; // if set to YES (default), app stops logging location at some point and doesn't resume in any timely fashion, all data points lost in between _locationManager.pausesLocationUpdatesAutomatically = NO; _locationManager.activityType = CLActivityTypeFitness; } return self; } // called early in program after login confirmed - (void) startCollectingLocation { [_locationManager startUpdatingLocation]; } - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { // logs to file when device is not in debug // always returns 1 NSLog(@"Location update count: %d",[locations count]); // some code here to handle location updates // - collect key location day in NSDictionary // - every N seconds send Network call to server to save (have tried 30 seconds, 15 minutes, 30 minute network intervals). Have also tried turning off network calls completely. // deferred updates starter if (!self.deferringUpdates) { if([CLLocationManager deferredLocationUpdatesAvailable]){ [_locationManager allowDeferredLocationUpdatesUntilTraveled:500 timeout:(NSTimeInterval)120]; // (have also tried large numbers, and "Infinite" self.deferringUpdates = YES; NSLog(@"Deferred updates start"); } else { NSLog(@"Deferred updates not available"); } } } - (void)locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error { if(!error){ _deferringUpdates = NO; NSLog(@"Deferred updates: finished"); } else { _deferringUpdates = NO; NSLog(@"Deferred updates: %@", [error localizedDescription]); } } 

如果设备连接到debugging器或充电器,设备将保持供电(不hibernate),因此不会进入延期模式。 延迟模式是一种功耗优化,可让设备进入hibernate状态。 如果设备由于其他原因而未安排睡眠,则启用延迟模式将不会强制其进入hibernate状态。 通过确保没有其他应用程序正在使用位置服务来尝试您的testing,并在屏幕closures的情况下从充电器断开连接。 运行一段时间后,重新插入并检查您的日志,您应该看到设备睡眠和延期更新。

从苹果的allowDeferredLocationUpdatesUntilTraveled:timeout:文档:

延迟更新仅在系统进入低功耗状态时才会提供。 延迟更新不会在debugging过程中发生,因为Xcode会阻止您的应用程序进入hibernate状态,从而阻止系统进入低功耗状态。

还值得注意的是,延期更新只有在locationManager.desiredAccuracy设置为kCLLocationAccuracyBest或者kCLLocationAccuracyBest时才可用; locationManager.distanceFilter也必须设置为kCLDistanceFilterNone。

从苹果的文档:

只有当设备上有GPS硬件可用,并且所需的准确性设置为kCLLocationAccuracyBest或kCLLocationAccuracyBestForNavigation时,位置pipe理器才允许延迟更新。

…位置pipe理器的distanceFilter属性必须设置为kCLDistanceFilterNone。

我一直在努力解决同样的问题,我可能已经find了一个解决这个问题的答案 – 至less它解决了我的问题,并获得延期更新一直为我工作。 我遵循了列表中的所有步骤,无论我做了什么,位置更新都不会推迟。 我想,我可能有其他运行的应用程序不允许系统进入睡眠状态,所以我杀死了多任务托盘中的所有其他应用程序。 我再次运行我的示例应用程序,…它的工作! 但故事并没有结束。 我稍后再尝试,即使在多任务托盘中没有运行其他应用程序,我也无法获取定位服务。 然后,我发现我的手机上有一个名为“Moves”的应用程序,即使手动杀死它,它也能保持自己的活力。 我不完全确定Moves是如何神奇地回到生活当你杀死它,但它(也许使用蓝牙和应用程序保存/恢复服务)。 即使它处于活动状态并跟踪您的位置,它也不会出现在多任务托盘中。 我认为只有手动启动的应用程序出现在托盘中 – 如果操作系统启动应用程序,它不会出现在托盘中。 但是我离题了……我能够通过禁止Move使用位置服务来获得延迟定位服务,以便在我的应用程序中始终如一地工作。 当我这样做,移动抱怨, 即使它不是在多任务托盘 。 看来,如果另一个应用程序正在使用位置服务(而不是推迟),你的应用程序也不会延期。

嗨最近与iOS 9 GM种子版本,我已经看到位置更新(allowDeferredLocationUpdatesUntilTraveled:超时:)没有得到推迟。相同的代码用于在iOS 8.4及以下版本的工作,它耗尽了我的设备的电池巨大的余地。

有什么我们需要明确设置或提及的iOS 9?没有find任何来自苹果文档

这是我实现的代码。

– (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {

if(!self.deferringUpdates){

[self.locationManager allowDeferredLocationUpdatesUntilTraveled:CLLocationDistanceMax timeout:30]; self.deferringUpdates = YES; }}

– (void)locationManager:(CLLocationManager *)manager didFinishDeferredUpdatesWithError:(NSError *)error {//停止推迟更新self.deferringUpdates = NO;

}

我还设置了allowBackgroundLocationUpdates属性,但即使这样也没有帮助。 self.locationManager.allowsBackgroundLocationUpdates = YES;

在iOS 9和更高版本中,无论部署目标如何,您还必须将位置pipe理器对象的allowBackgroundLocationUpdates属性设置为YES,以便接收后台位置更新。 默认情况下,这个属性是NO,它应该保持这种方式,直到你的应用程序主动需要后台位置更新。

https://developer.apple.com/library/prerelease/ios/documentation/Performance/Conceptual/EnergyGuide-iOS/LocationBestPractices.html

请让我知道我还需要做些什么

谢谢