ios,startMonitoringSignificantLocationChanges – 有时会破坏监控

我有更新用户位置的奇怪问题。 有时我的应用程序会更新位置,但有时会更新。 我不知道问题出在哪里,我的代码(来自AppDelegate.m)如下:

- (void)applicationDidEnterBackground:(UIApplication *)application { NSLog(@"Went to Background"); // Only monitor significant changes [locationManager startMonitoringSignificantLocationChanges]; } - (void)applicationDidBecomeActive:(UIApplication *)application { // Start location services locationManager = [[CLLocationManager alloc] init]; locationManager.desiredAccuracy = kCLLocationAccuracyBest; // Only report to location manager if the user has traveled 1000 meters locationManager.distanceFilter = 1000.0f; locationManager.delegate = self; locationManager.activityType = CLActivityTypeAutomotiveNavigation; [locationManager stopMonitoringSignificantLocationChanges]; [locationManager startUpdatingLocation]; } - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { // Check if running in background or not BOOL isInBackground = NO; if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) { isInBackground = YES; } if (isInBackground) { // If we're running in the background, run sendBackgroundLocationToServer [self sendBackgroundLocationToServer:[locations lastObject]]; } else { // If we're not in the background wait till the GPS is accurate to send it to the server if ([[locations lastObject] horizontalAccuracy] < 100.0f) { [self sendDataToServer:[locations lastObject]]; } } } -(void) sendBackgroundLocationToServer:(CLLocation *)location { bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ [[UIApplication sharedApplication] endBackgroundTask:bgTask]; }]; // Send the data [self sendDataToServer:location]; if (bgTask != UIBackgroundTaskInvalid) { [[UIApplication sharedApplication] endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; } } -(void) sendDataToServer:(CLLocation *)newLocation { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSString *lat = [NSString stringWithFormat:@"%.8f", newLocation.coordinate.latitude]; NSString *lng = [NSString stringWithFormat:@"%.8f", newLocation.coordinate.longitude]; [APIConnection SaveMyPositionWitLat:lat withLng:lng]; }); } 

我需要每小时更新一次位置,或者如果用户更改位置超过1000米。 我选择了第二种方式以节省电池,但我的解决方案无法正常工作。

非常感谢任何帮助,提前谢谢!

我不能肯定地说这是你们所有人的问题,但我会做出以下改变:

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Moved to didFinishLaunching... you should not be recreating every time app // becomes active. You can check for locations key in the options Dictionary if // it is necessary to alter your setup based on background launch // Start location services locationManager = [[CLLocationManager alloc] init]; locationManager.desiredAccuracy = kCLLocationAccuracyBest; // Only report to location manager if the user has traveled 1000 meters locationManager.distanceFilter = 1000.0f; locationManager.delegate = self; locationManager.activityType = CLActivityTypeAutomotiveNavigation; // Start monitoring significant locations here as default, will switch to // update locations on enter foreground [locationManager startMonitoringSignificantLocationChanges]; // Hold in property to maintain reference self.locationManager = locationManager; } 

在您的领导之后,这将是您的didBecomeActive方法中的所有内容(我将使用willEnterForeground ):

 - (void)willEnterForeground:(UIApplication *)application { [self.locationManager stopMonitoringSignificantLocationChanges]; [self.locationManager startUpdatingLocation]; } 

进入后台,仅返回重要位置更改:

 - (void)applicationDidEnterBackground:(UIApplication *)application { NSLog(@"Went to Background"); // Need to stop regular updates first [self.locationManager stopUpdatingLocation]; // Only monitor significant changes [self.locationManager startMonitoringSignificantLocationChanges]; } 

在您的委托方法中,我建议您取消所有条件后台测试。 如果应用程序在后台或在完成之前进入后台,我将包装在后台任务标识符中。 我也在全局线程上做出响应,所以我们不阻止UI(可选):

 - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations { UIApplication *app = [UIApplication sharedApplication]; __block UIBackgroundTaskIdentifier locationUpdateTaskID = [app beginBackgroundTaskWithExpirationHandler:^{ dispatch_async(dispatch_get_main_queue(), ^{ if (locationUpdateTaskID != UIBackgroundTaskInvalid) { [app endBackgroundTask:locationUpdateTaskID]; locationUpdateTaskID = UIBackgroundTaskInvalid; } }); }]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // You might consider what to do here if you do not ever get a location accurate enough to pass the test. // Also consider comparing to previous report and verifying that it is indeed beyond your threshold distance and/or recency. You cannot count on the LM not to repeat. if ([[locations lastObject] horizontalAccuracy] < 100.0f) { [self sendDataToServer:[locations lastObject]]; } // Close out task Identifier on main queue dispatch_async(dispatch_get_main_queue(), ^{ if (locationUpdateTaskID != UIBackgroundTaskInvalid) { [app endBackgroundTask:locationUpdateTaskID]; locationUpdateTaskID = UIBackgroundTaskInvalid; } }); }); } 

看看我的项目TTLocationHandler

在Github上了解更多使用Core Location的示例,以您希望的方式使用它。