ios - 应用程序进入后台后每 n 分钟获取一次用户位置

标签 ios objective-c iphone background locationmanager

我正在尝试实现 this post 中给出的建议.

不幸的是,我不清楚这些步骤。我尝试实现这些建议,但即使在我启动和停止 locationServices 之后,backgroundTimeRemaining 仍在继续减少。这就是我开发它的方式:

- (void)applicationDidEnterBackground:(UIApplication *)application {

    UIApplication*    app = [UIApplication sharedApplication];

    bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];

    // Start the long-running task and return immediately.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Do the work associated with the task.
        self.timer = nil;
        [self initTimer];

    });
}

初始化定时器:

- (void)initTimer {

    // Create the location manager if this object does not
    // already have one.
    if (nil == self.locationManager)
        self.locationManager = [[CLLocationManager alloc] init];

    self.locationManager.delegate = self;
    [self.locationManager startMonitoringSignificantLocationChanges];

    if (self.timer == nil) {
        self.timer = [NSTimer scheduledTimerWithTimeInterval:0.3
                                              target:self
                                            selector:@selector(checkUpdates:)
                                            userInfo:nil
                                             repeats:YES];
    }
}

检查更新:

- (void)checkUpdates:(NSTimer *)timer{
    UIApplication*    app = [UIApplication sharedApplication];
    double remaining = app.backgroundTimeRemaining;
    if(remaining < 580.0) {
        [self.locationManager startUpdatingLocation]; 
        [self.locationManager stopUpdatingLocation]; 
        [self.locationManager startMonitoringSignificantLocationChanges];
    }
    DbgLog(@"Reminaing %f", app.backgroundTimeRemaining);
}

有人对我的代码中可能存在的错误提出建议吗? initTimer 和 checkUpdates 都被调用,但仅在后台执行时间(+- 10 分钟)期间被调用。我希望该应用“永远”每 n 分钟更新一次位置。

我的应用程序的 UIBackgroundModes 设置为位置。

更新:

我现在正在重置 didUpdateToLocation 和 didFailWithError 上的计时器。但 backgroundTimeRemaining 仍然不断减少:

- (void)locationManager:(CLLocationManager *)manager 
didUpdateToLocation:(CLLocation *)newLocation 
       fromLocation:(CLLocation *)oldLocation {

NSLog(@"Did Update Location = %f / %f", [newLocation coordinate].latitude, [newLocation coordinate].longitude);

UIApplication*    app = [UIApplication sharedApplication];

bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    [app endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // Do the work associated with the task.

    [self initTimer];

});
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {

[self.locationManager stopUpdatingLocation]; 
UIApplication*    app = [UIApplication sharedApplication];

bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
    [app endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

// Start the long-running task and return immediately.
[self initTimer];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // Do the work associated with the task.

});

}

我还使计时器无效:

- (void)checkUpdates:(NSTimer *)timer{
UIApplication*    app = [UIApplication sharedApplication];
double remaining = app.backgroundTimeRemaining;
if(remaining < 580.0 && remaining > 570.0) {
    [self.timer invalidate];
    self.timer = nil;
    [self.locationManager startUpdatingLocation]; 
    [self.locationManager stopUpdatingLocation]; 
}
DbgLog(@"*************************Checking for updates!!!!!!!!!!! Reminaing %f", app.backgroundTimeRemaining);
}

最佳答案

对于那些在试图解决这个问题时做噩梦的人,我有一个简单的解决方案。

  1. 研究 raywenderlich.com 中的示例.示例代码完美运行,但不幸的是在后台定位期间没有计时器。这将无限期地运行。
  2. 使用以下代码片段添加计时器:

    -(void)applicationDidEnterBackground {
      [self.locationManager stopUpdatingLocation];
    
      UIApplication* app = [UIApplication sharedApplication];
    
      bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
      }];
    
      self.timer = [NSTimer scheduledTimerWithTimeInterval:intervalBackgroundUpdate
                                                    target:self.locationManager
                                                  selector:@selector(startUpdatingLocation)
                                                  userInfo:nil
                                                   repeats:YES];
    }
    
  3. 只是不要忘记在 info.plist 中添加“App registers for location updates”。

关于ios - 应用程序进入后台后每 n 分钟获取一次用户位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10235203/

相关文章:

ios - Podspec 验证错误 - 文件模式 : The spec is empty

iphone - 如何在 iPhone 中隐藏 Safari Mobile 浏览器底部按钮栏?

iphone - 两个选项栏按钮项

ios - 使用选项卡 View Controller 的 Xcode IOS 转换 View

ios - 如何将按钮连接到新的 View Controller iOS Swift?

objective-c - 从 Today 扩展应用程序发送系统事件

ios - UILabel 在 iOS7 中有一个奇怪的灰色顶线/边框,我该如何删除它?

iphone - 我怎样才能像 UIActionSheet 一样从屏幕底部呈现一个 UIView?

ios - ASNetworkImageNode gif 未加载

ios - 通过名称访问 Sprite 节点