XcodeのCapabilitiesに Background fetch
(下図の青枠部分) がありますが、これについて理解を深めたいと思います。
Background fetchとは
Appleは App Programming Guide for iOS - Fetching Small Amounts of Content Opportunistically でBackground fetchを以下のように紹介しています。定期的にコンテンツを確認する必要があるようなアプリでは有効かもしれません。
Apps that need to check for new content periodically can ask the system to wake them up so that they can initiate a fetch operation for that content. 出典: App Programming Guide for iOS - Fetching Small Amounts of Content Opportunistically
ただ、Background fetchはその「定期的」にというところについては保証はしておらず、システムがバランスを見てフェッチをすると説明が続いています。
Enabling this mode is not a guarantee that the system will give your app any time to perform background fetches. The system must balance your app’s need to fetch content with the needs of other apps and the system itself. After assessing that information, the system gives time to apps when there are good opportunities to do so. 出典: App Programming Guide for iOS - Fetching Small Amounts of Content Opportunistically
そのため、 Background fetch
は処理可能な時にやってくれればいいな (e.g., 最新のトレンド情報のダウンロードなど) といったような興味関心は高いが重要ではない情報を取得するなどの処理において有効で、毎時に必ず処理をさせないとアプリの動作が成り立たないような場合には不向きだと私は思います。
例えば、 Background fetch
の用例としてWWDC 2013のセッション What's New with Multitasking (25:30) では具体例を以下のように述べています。
また、同セッションの36:05では以下のように Background fetch
を説明しています。
実装方法
Updating Your App with Background App Refreshに大まかにやることが書いてあります。サンプルのソースコードも載っています。 以下はそのコードを転記したものです。
|
|
上記のコードでは以下の実装がされています。
UIApplication.shared.setMinimumBackgroundFetchInterval
の設定- UIApplicationDelegateの
performFetchWithCompletionHandler
を実装
コーディングに入る前にXcodeのCapabilitiesに Background fetch
をONにしておきます。
UIApplication.shared.setMinimumBackgroundFetchInterval
UIApplication.shared.setMinimumBackgroundFetchInterval(3600)
とありますが、このメソッドはアプリが別のバックグラウンドのフェッチ処理が開始されるまでの最小間隔(秒, TimeInterval
) で設定します。
ですので、この3600の場合は前回のフェッチ処理から少なくとも1時間は間隔を空けるという意味で、1時間毎にフェッチ処理をするというわけではありません。24時間待たないとフェッチ処理が実行されないこともあります。(後述の「Background fetchの実行タイミング」を参照)
上のコードでは具体的な数値を指定していますがUI Kitは以下の定数を提供しています。
定数名 | 説明 |
UIApplicationBackgroundFetchIntervalMinimum | システム (OS?) がサポートする最小のフェッチ間隔 |
UIApplicationBackgroundFetchIntervalNever | フェッチ操作を発生させないのに十分なフェッチ間隔 |
performFetchWithCompletionHandler
performFetchWithCompletionHandler
はシステムが呼び出します。このメソッド内ではバックグラウンド時に処理させたい内容を記述します。処理時間を10秒から30秒までに収めるのが良いとされています (根拠不明)。処理の最後に completionHandler
を呼ぶ必要があります。
デバッグ方法
前述の通り、 Background fetch
のフェッチのタイミングはわかりません。デバッグ時にもそれでは困りますからXcodeのDebug > Simulate Background Fetch は利用してフェッチされたとアプリに伝えることができます。
試しに前述のAppleのサンプルコードを使ったアプリを実機にインストールして動作を確認します。 Console.appにログが出力できるようにしておきます。
|
|
Background Fetchの設定が終わるとConsole.appにこういったログが出ます。
|
|
そして、performFetchWithCompletionHandlerが呼ばれ、処理が完了するとこのログが出ます。
|
|
また、エンドユーザーがアプリをキル (ホームボタンを2回押してアプリを上にスワイプ) した場合は、以下のメッセージがConsole.appに出力されます。
|
|
Background fetchの実行タイミング
「24時間待たないとフェッチ処理が実行されないこともあります」と述べましたが、アプリにログを仕込みBackground fetchがいつ実行されるのか確認してみました。
以下の状況で採取できたログです。
- 28日19時から翌日2時という時間帯でアプリをデバッグ実行していた
- アプリケーションは29日の午前中にはアプリをホームボタンを押してアプリスイッチャー?でプロセスをキルした
以下のログからBackground fetchは19時から翌日2時の時間帯に実行されていることがわかります。
|
|
Background fetchは24時間後には実行されるようです。またアプリを使っている時間帯をOSが覚えているように思えます。
まとめ
- フェッチの最小間隔は指定できますが、フェッチの実行タイミングは指定できません
- フェッチが始まると10秒から30秒までの間に処理を終わらす必要があるとされていますが根拠は明らかではありません
- フェッチは24時間後に実行される (少なくとも24時間以内に実行される保証はない)
- 上記の理由から、フェッチで取得しようとしている情報が取得ができていなくても大丈夫なようにアプリを設計する必要があります