2015-01-13 110 views
0

我寫了一個應用程序的監視器用戶的位置。位置服務在我的視圖加載時打開:IOS:當應用程序在後臺停止位置更新一段時間

// 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; 

// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7. 
if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) { 
    [self.locationManager requestAlwaysAuthorization]; 
} 

[self.locationManager startMonitoringSignificantLocationChanges]; 
NSLog(@"Started monitoring significant location changes"); 

如果我終止應用程序,而其活動位置服務停止。這是我寫的AppDelegate.m停止位置服務的代碼:

- (void)applicationWillTerminate:(UIApplication *)application { 
    // Called when the application is about to terminate. Save data if appropriate. See also    
     applicationDidEnterBackground:. 
    // Saves changes in the application's managed object context before the application terminates. 
    NSLog(@"entered terminate in delegate"); 
    [myController.locationManager stopUpdatingLocation]; 
    [myController.locationManager stopMonitoringSignificantLocationChanges]; 
    myController.locationManager = nil; 
    [self saveContext]; 
} 

我遇到了這樣的問題:如果我的應用程序已經在後臺,上述方法不調用,因此我無法關閉位置服務。要解決這個問題,我發現這個解決方案,我想:

- (void)applicationDidEnterBackground:(UIApplication *)application { 
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 

    UIApplication *app = [UIApplication sharedApplication]; 
    if ([app respondsToSelector:@selector(beginBackgroundTaskWithExpirationHandler:)]) { 
     self.bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ 
      // Synchronize the cleanup call on the main thread in case 
      // the task actually finishes at around the same time. 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       if (self.bgTask != UIBackgroundTaskInvalid) 
       { 
        NSLog(@"Marking bgTask as Invalid when we entered background"); 
        [app endBackgroundTask:self.bgTask]; 
        self.bgTask = UIBackgroundTaskInvalid; 
       } 
      }); 
     }]; 
    } 
} 

所以上述方案工作,如果我的應用程序是在後臺。但是,我注意到,如果讓我的應用程序長時間在後臺運行超過五分鐘,過期處理程序就會啓動。因此,如果我終止應用程序而不將它帶到前臺。位置服務圖標仍會顯示在手機上。我必須重新啓動應用程序或將其帶到前臺先終止它禁用定位服務踢代碼

如果我刪除這兩條線:

  [app endBackgroundTask:self.bgTask]; 
     self.bgTask = UIBackgroundTaskInvalid; 

然後停止位置服務工程在調試器連接五分鐘後找到。如果我讓它在後臺運行時間更長,那麼終止代碼從不會啓動。是因爲我沒有更改位置或應用程序最終死亡?

所以我的問題是,是否有另一種方式來確保應用程序正確停止位置服務監控,如果它在後臺一段時間?

謝謝...荷銀


編輯,我做更多的實驗,這裏是我的發現:

當連接到調試器,如果我等待11分鐘不時進入後臺模式,該方法willTerminate被調用:

2015-01-13 08:52:45.935 [441:37074] @@@AMRO--->applicationWillResignActive entered 

2015-01-13 08:52:46.642 [441:37074] @@@AMRO--->Entered background mode 

2015-01-13 08:55:42.697 [441:37074] @@@AMRO--->beginBackgroundTaskWithExpirationHandler called 

2015-01-13 09:03:26.265 [441:37074] entered terminate in delegate 

如果我試試這個沒有調試器,只能等待4分,終止函數不會被調用,我不必等待WH ole 11分鐘。

+0

看看這個帖子http://stackoverflow.com/questions/24778492/stop-location-updates-when-app-terminate/24778607#24778607,聽起來像一個類似的問題,還有,你打開位置更新背景模式? –

+0

@GuyS是的我需要在後臺模式下進行位置跟蹤。根據我的問題和實現細節,如果後臺應用程序在後臺運行超過5分鐘,則您提供的堆棧溢出鏈接解決方案不起作用 –

+0

您確定它是5分鐘而不是3分鐘嗎?在iOS 7後臺任務3分鐘後停止,我不知道它是否改變了ios 8(我不這麼認爲)。無論如何,我用這個帖子http://stackoverflow.com/questions/18901583/start-location-manager-in-ios-7-from-background-task獲取位置更新在後臺,我只是檢查,它的位置現在在後臺更新20分鐘...只需確保添加requestAlwaysAuthorization和plist字符串NSLocationAlwaysUsageDescription。 希望這有助於 –

回答

2

從蘋果的文檔:

應用程序終止

應用程序必須準備終止在任何時間發生,應該 迫不及待地保存用戶數據或執行其它關鍵任務。 系統啓動的終止是應用程序生命週期的正常組成部分。 系統通常會終止應用程序,以便它可以回收內存,並且 爲用戶啓動的其他應用程序騰出空間,但系統 也可能會終止行爲不當或未及時響應 事件的應用程序。

暫停的應用接收的時候都沒有終止通知;系統會殺死進程並回收相應的內存。如果 應用程序正在後臺運行,而不是暫停時, 系統調用applicationWillTerminate:它的應用程序委託之前 終止。當設備 重新啓動時,系統不會調用此方法。

除了系統終止您的應用程序,用戶可以明確使用多任務UI來終止 您的應用程序。用戶啓動的 終止與終止暫停的應用具有相同的效果。 應用程序的進程被終止並且沒有通知被髮送到應用程序。

https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html#//apple_ref/doc/uid/TP40007072-CH2-SW1

關於significantChangesLocation:

如果離開了顯著變化位置服務運行,您 iOS應用隨後被暫停或終止,服務 自動喚醒你的應用程序時新的位置數據到達。

https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/LocationAwarenessPG/CoreLocation/CoreLocation.html

如果您不希望您的應用程序通過significantChangeLocation喚醒你,你可以調用stopMonitoringSignificantLocationChanges時backgroundTimeRemaining即將到期。

Att。

+0

感謝您的回覆,從我的測試中,這是我收集的。我把我的應用程序用於驅動器。把它放在後臺,每次觸發位置更新時,我都會發出通知,以便在UI中看到它。所以這證明即使應用程序被暫停,我仍然收到通知。這在位置更新方面很好,但如果位置指針始終保持不變,用戶將會感到不安。我想我將不得不通過使用backgroundExpirationHandler和定時器組合來停止和啓動位置服務來解決此問題 –

相關問題