需要讓APP像Nike+或RunKeeper那樣,就算將APP退到背景,也會持續記錄GPS位置。
但是不知道為什麼在背景執行了20分鐘就停止了。研究後發現原來少了一行關鍵程式。
locationManager.pausesLocationUpdatesAutomatically = false
是否讓位置更新自動停止 ,預設為true
時間到了20分鐘左右,就會自動停止
完整範例下載
以下簡介一下程式的內容,完整程式請直接下載範例
設定APP權限
Capabilities->Background Modes 選擇 ON
勾選 Location updates

加入GPS相關函式庫
General->Linked Frameworks and Libraries
點選 + ,加入 CoreLocation.framework

因為是Swift的關係,需要加入Header File

檔案的內容加上
#import <CoreLocation/CoreLocation.h>

建立Header檔案的關聯
Build Settings-> Swift Compiler-Code Generation
->Objective-C Bridging Header 填入 LocationTrack/Header.h
LocationTrack為專案資料夾
Header.h是剛剛建立的Header File

編輯請求權限時的說明文字
編輯Info.plist
加入 NSLocationAlwaysUsageDescription
裡面的文字,是APP請求相關權限時,向使用者說明的文字內容
以下兩個選擇其中一個填入,差別在於,一個是向使用者請求APP使用期間時,才使用GPS;一個是不管是不是APP使用期間,都可以使用GPS
NSLocationWhenInUseUsageDescription APP使用期間才使用GPS的文字說明
NSLocationAlwaysUsageDescription 任何時間都可以使用GPS的文字說明

向使用者請求權限的畫面

權限的差別
設定->隱私權->定位服務
可以看到兩個權限的差別

當APP的權限是選擇"使用App期間"才可以使用GPS時
將APP退到背景時,會顯示正在使用您的位置
像Nike+和RunKeeper

在程式中,要求請求權限的部份,以下選擇一個就可以了
//在APP使用期間才能使用GPS
locationManager.requestWhenInUseAuthorization()
//隨時都可以使用GPS
locationManager.requestAlwaysAuthorization()
範例APP簡介
這個APP在點選"START開始記錄座標"按鈕時,會開始記錄GPS
把GPS資料寫入GPSRecord.plist檔案裡
在開啟APP時,會先讀取GPSRecord.plist檔案的內容
使用iTools等工具就可以將這個記錄檔案取出

初始化
在ViewController當中先定義一些變數
並加上CLLocationManagerDelegate

初始化CLLocationManager
@IBAction func btnStartGPS(sender: UIButton) {
let btnStartGPSLabel: String = btnStartGPS.titleLabel!.text!
if((btnStartGPSLabel).rangeOfString("START")?.startIndex == (btnStartGPSLabel).startIndex){
//簡易的判斷現在是要停止或是開始
btnStartGPS.setTitle("STOP停止記錄座標", forState: UIControlState.Normal)
//初始化變數
locationManager = CLLocationManager()
locationManager.delegate = self
//設定精確度
locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
//相當重要的一行
//如果不加的話,會在背景執行20分鐘左右,就停止記錄了
locationManager.pausesLocationUpdatesAutomatically = false
if #available(iOS 9.0, *){
locationManager.allowsBackgroundLocationUpdates = true
}
//---請求權限---
//在APP使用期間才能使用GPS
//locationManager.requestWhenInUseAuthorization()
//隨時都可以使用GPS
locationManager.requestAlwaysAuthorization()
//----------
//設置距離篩選器,表示設備至少移動?米,才通知委託更新
locationManager.distanceFilter = 10
locationManager.startUpdatingLocation()
}else{
btnStartGPS.setTitle("START開始記錄座標", forState: UIControlState.Normal)
locationManager = nil
}
}
座標更新的事件
//座標有更新時會呼叫這裡
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//經緯度
var userLocationLat: String = String(locations[0].coordinate.latitude)
var userLocationLon: String = String(locations[0].coordinate.longitude)
var GPSText = getNowTime() + "=>" + userLocationLat + "," + userLocationLon
textGPS.text = GPSText + "\n" + textGPS.text
setPlistContent(GPSText)
}
需要設定BackgroundTask,才可以在背景執行override func viewWillAppear(animated: Bool) {
myTimer.invalidate()
//停止背景執行
backgroundTask = UIBackgroundTaskInvalid
}
override func viewWillDisappear(animated: Bool) {
//當程式進入背景時,執行這段
//這段是測試用,可以不用有這段
//監控APP是否還有在執行
myTimer.invalidate()
myTimer = NSTimer.scheduledTimerWithTimeInterval(1.0,
target: self,
selector: "timerMethod:",
userInfo: nil,
repeats: true)
//加這個,才會在背景執行
//時間到了會執行這裡
backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {
[unowned self] in
}
assert(backgroundTask != UIBackgroundTaskInvalid)
}
完整範例下載
------------
iOS后台持续定位并定时上传