TMPTaskCompletionManagerの公開に伴い、task completionについてまとめてみます。
task completion は iOS4 で導入されたマルチタスク処理方式の一つです。アプリがバックグラウンドモードへ入った後も、実行中の処理を継続したいときに使います。実行可能時間は、iOS6までは最長10分間。iOS7では最長3分間へ短縮されました。
バックグラウンドでの実行要求は、
- [UIApplication beginBackgroundTaskWithExpirationHandler:]
で行います。要求は何度でも可能です。
処理が終了したなど、バックグラウンドでの実行が不要になった場合には、
- [UIApplication endBackgroundTask:]
を呼び出さなければなりません。このメソッドを呼び出すか、規定時間が経過した場合、アプリケーションはバックグラウンド処理を終了し、サスペンド状態へ入ります。
StackOverflowでも言及されているように、beginBackgroundTaskWithExpirationHandler:は、名前に「begin」と付いているものの、実際にはバックグラウンド処理を開始しません。このメソッドは、OSに対し、バックグラウンドでの処理継続を要求するために使います。
beginBackgroundTaskWithExpirationHandler:が呼び出される毎に、OSはその回数を記録します(動作可能時間は初回要求時から増えません)。この数値が1以上である場合、OSは、アプリがバックグラウンド処理を要求していると判断します。この回数は、endBackgroundTask:で減算されます。0になった時点で、OSはアプリケーションはバックグラウンド処理を望んでいないと判断します。メモリ管理のリファレンスカウントと同じ原理です。
言い換えれば、endBackgroundTask:を呼び出すまで、アプリケーションはバックグラウンド処理を要求し続けていることになります。例えば、アプリがフォアグラウンドへ復帰するなど、バックグラウンド処理が不要になった場合には、明示的にendBackgroundTask:を呼びださなければなりません。
Appleが公開している
iOS App Programming Guideの
Executing a Finite-Length Task in the Backgroundでは言及されていないためか、
「Cocoaの日々」の
「[iOS] バックグラウンド実行見本(Task Completion)」などを除いて、あまりフォアグラウンド復帰時の処理に関し、言及していないように感じています。
この動作を確認するために TaskCompletionSample を作成しました。
https://github.com/n-miyo/TaskCompletionSample
このアプリはアプリケーションバッジを1秒ごとに増加させます。beginBackgroundTaskWithExpirationHandler:の実行はviewDidLoadで行われ、endBackgroundTask:は実行されません。
アプリをバックグラウンドへ落とすと、バッジの増加を通じてバックグラウンド処理を確認できます。アプリを一度フォアグラウンドへ復帰させ、再度バックグラウンドへ遷移させてみます。この処理の過程では新たにbeginBackgroundTaskWithExpirationHandler:を呼び出していませんが、アプリはバックグラウンド実行を継続可能です。
画面の「clear at 'didBecomeActive'」スイッチをONにすると、- [AppDelegate applicationDidBecomeActive:]実行時、endBackgroundTask:を実行するようになります。
この状態で、一度アプリをバックグラウンドへ遷移させ、再度フォアグラウンドへ遷移させた後、再度アプリをbeginBackgroundTaskWithExpirationHandler:へ移行させると、endBackgroundTask:との呼び出し回数が釣り合い、以後バックグラウンドでの実行は行われません。
さて、バックグラウンド処理を要求する場合、時間切れ時に実行されるタスクを登録し、その中でもendBackgroundTask:を実行する必要があります。これらは定形で書けますが、毎回書くのは面倒なものです。
また、複数のタスクをバックグラウンド登録した場合、それらをフォアグラウンド復帰のタイミングで一斉にキャンセルするには、すべてのタスクIDを管理しなければなりません。
これらの比較的定形でありながら、毎回書くのが面倒になるコードをまとめたものが、先に公開した TMPTaskCompletionManagerになります。使い方などは、「
iOS の task completion をサポートする TMPTaskCompletionManager を公開しました」を御覧ください。
ご意見などお待ちしております。