iOS不是典型的后台位置跟踪计时器问题
我正在开发一个示例应用程序,跟踪用户在后台的位置,但我不想离开位置服务始终启用,但在我的计时器中的某些行为不正确。
我的想法是,每x分钟,服务继续,当它有一个正确的新位置,它被释放,现在被设置为10秒,只是为了testing。 (显着位置变化没有窍门,没有足够的指责)
我search了很多(iOS开发人员中心+ StackOverflow),并find了“新的”后台位置function,它允许您在使用beginBackgroundTaskWithExpirationHandler,几个模块和一个计时器后,在运行后10分钟后运行代码。
我将背景模式设置为“位置”,现在我认为我不需要处理背景时间的结束(首先,我想每15-20秒获取一个位置)
代码工作“很好”,但是:
- 定时器有时会发生,有时不会。
- 计时器启动时,至less需要10分钟才能完成。
- 在操作系统中的一些随机操作(如进入search桌面)似乎估计计时器开火(不知道这一点,我不知道如何可能,但它是…)
通过代码将是另一个问题。
应用程序的方法:
// applicationDidEnterBackground
- (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]; }];}
// checkUpdates
- (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中设置的UIBackgroundModes键的“位置”值。
您可以使用beginBackgroundTaskWithExpirationHandler扩展您允许在后台运行的时间(如果您尚未设置“位置”),但应该始终与相应的结束呼叫配对。
好的,问题是我调用beginBackgroundTaskWithExpirationHandler两次,一个在ApplicationDidEnterBackground和另一个在initTimer内 …