これは2014年頃、Swiftが発表される直前の話。
バックグラウンドになってもどうにか処理をつづけられないかという依頼があって、いろいろためしてみたメモ。
知っての通りiOSにはバックグラウンドに厳しい制約があり基本無理だがいくつか方法はあった
-
BackgroundFetch(Background App Refresh Tasks)をつかう
iOSが任意のタイミングでアプリの処理を30秒だけ実行してくれる。
iOS7からだったので却下した -
VoIPアプリになる
VoIPアプリではないので却下 -
位置情報をバックグラウンドで取得
他アプリでも採用されていた方法だったのでこれをやってみた
いまはBackground ProcessingやBackgroundNotificationの選択肢もあるが当時はなかったので除外
位置情報取得
CoreLocation.framework
の追加、CapabilityからBackground Modes
を追加してLocation updates
にチェックをいれておく
当時はObjective-cで書いていたが、今Objective-cを残してもしょうがないのでSwiftで記載する
var locationManager: CLLocationManager = {
var locationManager = CLLocationManager()
locationManager.allowsBackgroundLocationUpdates = true
locationManager.desiredAccuracy = kCLLocationAccuracyKilometer
locationManager.distanceFilter = 1
return locationManager
} ()
allowsBackgroundLocationUpdates
をtrueにしておくとバックグラウンドで受信できる
func startLocation() {
locationManager.startMonitoringSignificantLocationChanges() // 大幅に位置が変更した時のみ位置情報を取得する
}
startMonitoringSignificantLocationChanges
を使うと位置情報が大きく動いたときだけupdateされる
extension AppDelegate: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let status = UIApplication.shared.applicationState
if status != .background {
return
}
NSLog("test application update location")
task.execute()
}
}
位置情報の変更を検知したらバックグラウンドタスクを実行、今回はバックグラウンドで動いていることがわかりやすいようにタスクの実行をバックグラウンドでのみ行う。
class BackgroundTask {
private var loopCount = 0
private var isExecuting = false
private let PrefKey = "countValue"
func execute() {
if isExecuting { return }
DispatchQueue.global().async {
self.isExecuting = true
self.loopCount = UserDefaults.standard.integer(forKey: self.PrefKey)
while(true) {
NSLog("test application background task %d", self.loopCount)
sleep(1)
self.loopCount = self.loopCount + 1
UserDefaults.standard.setValue(self.loopCount, forKey: self.PrefKey)
}
}
}
}
検証用のバックグラウンドタスク、ただ1秒おきにログを表示するだけ
結果
検証はシミュレータのLocationからFree Driveをつかって行った
2020-12-06 21:28:29.373625+0900 LaunchLocationInBackground[2189:105006] test application enter foreground
2020-12-06 21:28:32.634231+0900 LaunchLocationInBackground[2189:105006] test application enter background
2020-12-06 21:28:38.703424+0900 LaunchLocationInBackground[2189:105006] test application update location
2020-12-06 21:28:38.710385+0900 LaunchLocationInBackground[2189:105264] test application background task 0
2020-12-06 21:28:39.759649+0900 LaunchLocationInBackground[2189:105264] test application background task 1
2020-12-06 21:28:40.821763+0900 LaunchLocationInBackground[2189:105264] test application background task 2
2020-12-06 21:28:41.858983+0900 LaunchLocationInBackground[2189:105264] test application background task 3
2020-12-06 21:28:42.959856+0900 LaunchLocationInBackground[2189:105264] test application background task 4
2020-12-06 21:28:43.967623+0900 LaunchLocationInBackground[2189:105264] test application background task 5
2020-12-06 21:28:45.003097+0900 LaunchLocationInBackground[2189:105264] test application background task 6
2020-12-06 21:28:46.037451+0900 LaunchLocationInBackground[2189:105264] test application background task 7
2020-12-06 21:28:47.138904+0900 LaunchLocationInBackground[2189:105264] test application background task 8
2020-12-06 21:28:48.235930+0900 LaunchLocationInBackground[2189:105264] test application background task 9
2020-12-06 21:28:49.258731+0900 LaunchLocationInBackground[2189:105264] test application background task 10
2020-12-06 21:29:32.255424+0900 LaunchLocationInBackground[2189:105006] test application update location
2020-12-06 21:29:32.255519+0900 LaunchLocationInBackground[2189:105264] test application background task 11
2020-12-06 21:29:33.323138+0900 LaunchLocationInBackground[2189:105264] test application background task 12
2020-12-06 21:29:34.425526+0900 LaunchLocationInBackground[2189:105264] test application background task 13
2020-12-06 21:29:35.434688+0900 LaunchLocationInBackground[2189:105264] test application background task 14
2020-12-06 21:29:36.526842+0900 LaunchLocationInBackground[2189:105264] test application background task 15
2020-12-06 21:29:37.535671+0900 LaunchLocationInBackground[2189:105264] test application background task 16
2020-12-06 21:29:38.622164+0900 LaunchLocationInBackground[2189:105264] test application background task 17
2020-12-06 21:29:39.658490+0900 LaunchLocationInBackground[2189:105264] test application background task 18
2020-12-06 21:29:39.698484+0900 LaunchLocationInBackground[2189:105006] test application update location
2020-12-06 21:29:40.672103+0900 LaunchLocationInBackground[2189:105264] test application background task 19
2020-12-06 21:29:41.681671+0900 LaunchLocationInBackground[2189:105264] test application background task 20
2020-12-06 21:29:42.747317+0900 LaunchLocationInBackground[2189:105264] test application background task 21
2020-12-06 21:29:43.818607+0900 LaunchLocationInBackground[2189:105264] test application background task 22
2020-12-06 21:29:44.830959+0900 LaunchLocationInBackground[2189:105264] test application background task 23
2020-12-06 21:29:45.855771+0900 LaunchLocationInBackground[2189:105264] test application background task 24
2020-12-06 21:29:46.954273+0900 LaunchLocationInBackground[2189:105264] test application background task 25
2020-12-06 21:29:48.055699+0900 LaunchLocationInBackground[2189:105264] test application background task 26
2020-12-06 21:29:49.065966+0900 LaunchLocationInBackground[2189:105264] test application background task 27
2020-12-06 21:29:50.097980+0900 LaunchLocationInBackground[2189:105264] test application background task 28
application enter background
でバックグラウンドに突入してから、application update location
でアプリが起動し、バックグラウンドタスクが実行されている。
また、バックグラウンド生存期間が終了したあとも位置情報の更新によって続きから実行されている。
昔試したときはバックグラウンドでの実行時間は3分あったきがするのだが短くなったのだろうか