ios延迟位置更新无法推迟

时间:2014-04-28 21:01:42

标签: ios location core-location deferred

我正在研究为iOS活动跟踪器使用延迟位置更新,它允许在后台使用位置服务。我已经实现了建议的代码片段(见下文)。在Xcode调试中,延迟位置尝试启动几次,直到位置数据以每秒大约1次进入。之后,它声称成功启动延迟,并且在指定的时间段到期后,完成触发器的回调也会成功。但是在此期间,位置处理程序仍然每秒运行一次。我已经读到这是因为手机还没有准备好进入后台,而Xcode中的测试就是这样做的。注意,关闭屏幕后立即调用AppDelegate的“didEnterBackground”事件处理程序,并在重新打开应用程序时重新启动。

我运行相同的代码,手机断开连接作为另一个测试,靠近窗户,GPS,屏幕关闭,或切换到完全不同的应用程序,它仍然从来没有真正推迟更新。我可以说,因为网络更新仍然每30秒进入一次,而不是下面代码示例中所需的120秒间隔。

实际让延期工作还需要什么,因为在启动它们时没有错误,并且它们确实得到了完成回调?为什么即使应用程序进入后台,位置更新仍以每秒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]);
    }
}

3 个答案:

答案 0 :(得分:5)

如果设备连接到调试器或充电器,设备将保持通电(非休眠),因此不会进入延迟模式。延迟模式是功率优化,允许设备休眠。如果由于其他原因未将设备安排为休眠,则启用延迟模式将不会强制其进入休眠状态。通过确保没有其他应用程序正在使用位置服务,并在关闭屏幕时将其与充电器断开连接来尝试测试。运行一段时间后,重新插入并检查日志,您应该看到设备处于睡眠状态并延迟更新。

来自Apple的 allowDeferredLocationUpdatesUntilTraveled:timeout:文档:

  

只有在系统进入低功耗状态时才会传递延迟更新   州。调试期间不会发生延迟更新,因为Xcode   防止您的应用程序休眠,从而阻止系统   进入低功率状态。

值得注意的是,延迟更新仅在locationManager.desiredAccuracy设置为kCLLocationAccuracyBest或kCLLocationAccuracyBest时可用; locationManager.distanceFilter也必须设置为kCLDistanceFilterNone。

来自Apple的文档:

  

...只有当设备上有GPS硬件并且所需精度设置为kCLLocationAccuracyBest或kCLLocationAccuracyBestForNavigation时,位置管理器才允许延迟更新。

  

...位置管理器的distanceFilter属性必须设置为kCLDistanceFilterNone。

答案 1 :(得分:4)

我一直在努力解决同样的问题,我可能已经找到了一个解决这个问题的答案 - 至少它解决了我的问题并得到了延期更新,我一直在努力。 我按照this list中的所有步骤操作,无论我做什么,位置更新都不会推迟。在我看来,我可能有其他运行的应用程序不允许系统睡眠,所以我杀了多任务托盘中的所有其他应用程序。我再次运行我的示例应用程序......它工作了! 但故事并没有结束。我稍后再试一次,即使多任务托盘中没有其他应用程序运行,我也无法获得推迟的位置服务。然后我突然意识到我的手机上有一个名为&#34; Moves&#34;即使你手动杀死它也能保持活着。我不能完全确定当你杀死它时神奇地恢复生命,但确实如此(可能使用蓝牙和应用程序保存/恢复服务)。即使它存在并且跟踪您的位置,它也不会出现在多任务托盘中。我认为只有手动启动的应用程序会出现在托盘中 - 如果操作系统启动应用程序,则它不会出现在托盘中。但我离题了...... 通过禁止Moves使用位置服务,我能够在我的应用中获得延迟位置服务以始终如一地。当我这样做时,Moves抱怨即使它不是在多任务处理托盘。似乎如果另一个应用程序使用位置服务(而不是推迟),您的应用程序也不会推迟。

答案 2 :(得分:1)

您最近使用iOS 9 GM种子版本,我看到位置更新(allowDeferredLocationUpdatesUntilTraveled:timeout :)没有延迟。相同的代码曾经在iOS 8.4及以下版本中工作。它耗尽了我的设备&#39; s电池很大。

我们需要为iOS 9明确设置或提及吗?没有从Apple文档中找到任何内容

这是我实施的代码。

- (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;

}

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

在iOS 9及更高版本中,无论部署目标如何,您还必须将位置管理器对象的allowsBackgroundLocationUpdates属性设置为YES,以便接收后台位置更新。默认情况下,此属性为NO,并且应该保持这种状态,直到您的应用主动要求更新后台位置为止。

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

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

由于