2014-10-09 82 views
15

我有後臺模式對位置服務和瞄準位置(經度和緯度)發送到服務器每30分鐘一班。現在我在控制檯上打印相同的內容。它似乎工作了一段時間,但我想知道如何在這種情況下使用NSTimer。我應該從哪裏調用它?發送位置,每30分鐘更新斯威夫特

import UIKit 
import CoreLocation 

@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate { 

    var window: UIWindow? 
    var locationManager = CLLocationManager() 

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 
     // Override point for customization after application launch. 
     return true 
    } 

    func applicationWillResignActive(application: UIApplication) { 
     // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 
     // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 
    } 

    func applicationDidEnterBackground(application: UIApplication) { 
     // 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. 

     self.locationManager.delegate = self 
     self.locationManager.startUpdatingLocation() // I know i should be using signification location option here. this is just for testing now. 
    } 

    func locationManager(manager: CLLocationManager!, didUpdateToLocation newLocation: CLLocation!, fromLocation oldLocation: CLLocation!) { 
     self.sendBackgroundLocationToServer(newLocation); 
    } 

    func sendBackgroundLocationToServer(location: CLLocation) { 
     var bgTask = UIBackgroundTaskIdentifier() 
     bgTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {() -> Void in 
      UIApplication.sharedApplication().endBackgroundTask(bgTask) 
     } 

     println(location.coordinate.latitude) 

     if (bgTask != UIBackgroundTaskInvalid) 
     { 
      UIApplication.sharedApplication().endBackgroundTask(bgTask); 
      bgTask = UIBackgroundTaskInvalid; 
     } 
    } 

    func applicationWillEnterForeground(application: UIApplication) { 
     // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 
     application.beginBackgroundTaskWithExpirationHandler{} 
    } 

    func applicationDidBecomeActive(application: UIApplication) { 
     // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 
     application.beginBackgroundTaskWithExpirationHandler{} 
    } 

    func applicationWillTerminate(application: UIApplication) { 
     // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 
     application.beginBackgroundTaskWithExpirationHandler{} 
    } 


} 

也許打電話application.beginBackgroundTaskWithExpirationHandler{}是個壞主意?我在這裏可以選擇哪些選項?

+0

順便說一句,委託方法'didUpdateToLocation:fromLocation'已被棄用 - 指CLLocationManagerDelegate文檔 – Paulw11 2014-10-09 04:44:17

回答

10

beginBackgroundTask...的想法是啓動一個有限長度的任務,以便如果用戶離開應用程序,它將繼續在後臺任務中運行一段短的有限時間段(我相信3分鐘)。在時間用完之前,您必須致電endBackgroundTask,否則應用程序將立即終止。

所以,可悲的是,後臺任務機制並不適合您所期望的意圖。但是,有一組特殊的背景模式,設計用於在一組狹窄的功能(VOIP,音頻等)之外進行後臺操作。欲瞭解更多信息,請參閱App Programming Guide for iOS: Background Execution實施長期運行任務部分。

現在,其中一種背景模式是「位置」服務。因此,如果這是您的應用程序的一個主要功能,對於正常功能至關重要,那麼您可以註冊location背景模式,並且您的應用程序將繼續在後臺運行。從那裏,你可以監視位置更新,如果足夠的時間已過,觸發某個過程。但是,如果此背景位置模式不是您的應用程序的基本功能,Apple很可能會拒絕您的應用程序請求其不需要的背景模式。


順便說一下,您應該知道,啓動標準位置服務可能會耗盡設備電池。您可以考慮使用電池效率爲"significant change" location service。這也有每次用戶移動一定距離時自動喚醒您的應用程序的優點(例如,以km爲單位;我相信這是通過移動到不同的手機信號塔觸發的)。

+0

的答案嘿@Rob,謝謝。是的,我已經使用了背景模式進行定位,而且位置確實是應用程序的中心部分。此外,此應用程序僅適用於內部用戶/臨時用戶。話雖如此,你能否給我一個例子或者說明我將如何在這裏使用NSTimer? – psharma 2014-10-09 19:09:08

+0

嗨@Rob,謝謝你的回答。這有很大幫助。是的,我意識到這消耗電池,但因爲它的特殊用途,它確定:)。另外,我會使用重大更改。現在我真的幫助我測試日誌。再次感謝。 – psharma 2014-10-10 00:42:05

+0

@Rob,你所描述的方法在模擬器中爲我工作,但不在設備上。任何可能出錯的想法? – nbbk 2017-05-18 13:17:39

3

試試這個:

  • 讓位置服務是獨生子。通過NSNotificationCenter

NSNotification

  • AppDelegatewillEnterBackGround,你發送通知其註冊的話,你的單身開始updatingLocation並將其發送到服務器時,接收到的位置數據。

  • 8

    的音符夫婦,因爲我們一直在爭取位置的問題,並與似乎並沒有喚醒我們的後臺應用程序掙扎。

    1. 只要您的應用程序沒有被暫停,NSTimer就是好的。當然,它在後臺,但只有它可以從iOS(APN,位置......)接收通知。最終,當你在BG中跑步時,你的計時器將停止射擊。所以,你依靠其中一種BG模式來踢你。

    2. 如果您正在使用CLLocationManager.startUpdatingLocation,你會發現,你不幹那些收到後位。特別是當電話放鬆並嘗試入睡時。這是因爲CLLocationManager.pausesLocationUpdatesAutomatically這個功能很差的功能,當它設置爲「true」(DEFAULT設置)時,決定停止發送這些功能。您可以將其設置爲「false」,並且您將繼續獲得您的位置更新。這幾乎可以確保你的應用程序做你想要的。

    3. 如上所述,您必須確保何時獲得您的locationManager.didUpdateLocations回調函數,以便在處理該信息併發送網絡數據時開始backgroundTask以保持應用程序正常工作。但你似乎明白這一點。

    4. 剛剛醒來足夠長的時間來記錄位置更新並不是那麼糟糕。只要確保你沒有產生你的網絡代碼,除非你明確地達到了30分鐘的期望值。