2014-01-29 32 views
6

我有更新用戶的位置奇怪的問題。有時我的應用更新位置,但不時更新。我不知道在哪裏的問題,我的代碼(從AppDelegate.m)低於:ios,startMonitoringSignificantLocationChanges - 有時會中斷監視

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

    }); 
} 

我需要更新位置,每隔一小時,如果用戶改變位置更然後千米。我選擇了第二種方式來節省電池,但是我的解決方案無法按需要工作。

我將不勝感激任何幫助,提前致謝!

回答

31

我不能肯定地說,如果這是你們所有的問題,但我會做如下修改:

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

在你的委託方法中,我建議取出所有的條件背景測試。我在後臺任務標識符中進行包裝,以防應用程序在後臺或在完成前進入後臺。我也是響應在全局線程,所以我們不會阻止用戶界面(可選):

- (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上使用的核心位置,你想使用的方式的一些例子它。

+0

Thx,這解決了我的問題,但我應該改變我的代碼每小時獲取位置? – Nizzre

+0

你會認爲這將需要後臺模式,並設置一個完全可能的計時器,但我不確定蘋果會批准它。爲了讓您的用戶免於使用瘋狂的電池,我會再次建議您注意一點。如果您有重大改變概念和區域監測工作,您可以對設備位置保持合理的想法。如果他們沒有移動,沒有意義不斷檢查。無論如何,這是另一個我想到的問題。 –

+2

偉大的工作在這裏@DeanDavids。剛剛檢查你的圖書館! – wprater

相關問題