iOS不是典型的后台位置跟踪计时器问题

iOS不是典型的后台位置跟踪计时器问题,ios,background,nstimer,core-location,objective-c-blocks,Ios,Background,Nstimer,Core Location,Objective C Blocks,我正在开发一个示例应用程序来跟踪用户在后台的位置,但我不想让位置服务始终处于启用状态,但我的计时器中的某些东西无法正常工作 我的想法是,每x分钟,服务就会继续,当它有一个正确的新位置时,它会再次发布,现在设置为10秒,只是为了测试。(明显的位置变化不起作用,不够准确) 我搜索了很多(iOS开发中心+StackOverflow),找到了“新”的后台位置功能,它允许您在进入后台后10分钟内运行代码,使用beginBackgroundTaskWithExpirationHandler、几个块和一个计时

我正在开发一个示例应用程序来跟踪用户在后台的位置,但我不想让位置服务始终处于启用状态,但我的计时器中的某些东西无法正常工作

我的想法是,每x分钟,服务就会继续,当它有一个正确的新位置时,它会再次发布,现在设置为10秒,只是为了测试。(明显的位置变化不起作用,不够准确)

我搜索了很多(iOS开发中心+StackOverflow),找到了“新”的后台位置功能,它允许您在进入后台后10分钟内运行代码,使用beginBackgroundTaskWithExpirationHandler、几个块和一个计时器

我将背景模式设置为Location,现在我认为我不需要处理背景时间的结束(首先,我希望每15-20秒获得一个位置)

代码运行“良好”,但:

  • 计时器有时启动,有时不启动
  • 计时器启动时,至少需要10分钟
  • 操作系统中的一些随机操作(如进入搜索桌面)似乎会估计要触发的计时器(不确定这一点,我不知道这是怎么可能的,但它确实存在…)
在代码结束后,将是另一个qüestion

appdelegates的方法:

//应用程序标识符背景

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

NSLog(@"to background");

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.
    _triggertimer = nil;
    [self initTimer];

});
NSLog(@"backgroundTimeRemaining: %.0f", [[UIApplication sharedApplication] backgroundTimeRemaining]);}
//initTimer

- (void) initTimer{
NSLog(@"InitTimer ");


UIApplication *app = [UIApplication sharedApplication];

bgTask = [app beginBackgroundTaskWithExpirationHandler:^{



_triggertimer = [NSTimer scheduledTimerWithTimeInterval:10.0
                                                     target:self
                                                   selector:@selector(checkUpdates:)
                                                   userInfo:nil
                                                    repeats:YES];

[[NSRunLoop currentRunLoop] addTimer:_triggertimer forMode:NSDefaultRunLoopMode] ;
[[NSRunLoop currentRunLoop] run];

}];}
//检查更新

- (void)checkUpdates:(NSTimer *)timer{

NSLog(@"CheckUpdates ");

UIApplication*    app = [UIApplication sharedApplication];

if (nil == _locationManager) _locationManager = [[CLLocationManager alloc] init];

_locationManager.delegate = self;


_locationManager.distanceFilter = 10;
_locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters;

[_locationManager startUpdatingLocation];
[_locationManager startMonitoringSignificantLocationChanges];



double remaining = app.backgroundTimeRemaining;
NSLog(@"Reminaing %f", remaining);}
我尝试了很多方法来解决这个问题,也许我弄错了或者错过了什么。。。你看到了什么?可能是一些概念上的错误,我试图介绍我自己的块,我还没有领域他们

顺便问一下,为什么我找到的所有代码在使用beginBackgroundTaskWithExpirationHandler执行任何操作之前都包含这个

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

我以为这是为了拍摄600秒的背景。。。但我不确定

当你的应用程序处于后台时,计时器将不再启动,除非你在应用程序的info.plist中设置了“location”值


您可以使用beginBackgroundTaskWithExpirationHandler延长允许在后台运行的时间(如果您没有设置“位置”),但这应该始终与相应的结束调用配对

好的,问题是我调用beginBackgroundTaskWithExpirationHandler两次,一次在ApplicationIdentinterBackground中,另一次在initTimer

我不想说,但我已经设置了UIBackgroundModes键…:(因此结束调用是?bgTask=[app beginbackgroundtask withexpirationhandler:^{[app endBackgroundTask:bgTask];bgTask=UIBackgroundTaskInvalid;}];它应该在调度之前(正如我在代码中所做的那样)或之后\u async??