iOSアプリの状態遷移
iOS4.0からアプリのマルチタスキングが導入され、アプリはバックグラウンドという状態を持てるようになりました。それ以前にはアプリの状態というのは起動中(アクティブ)かそうでないかぐらいの区別しかなかったものが、これによってぐぐっと複雑になり、アプリケーションガイドを一度見たくらいではたぶん完全には理解できなくなったのではないでしょうか。(ガイドにはちょっと嘘も書いてあります)
アプリケーションガイドによると、アプリの状態というのは下記5種類があるそうです。
・非実行
・非アクティブ
・アクティブ
・バックグラウンド
・一時停止(サスペンド)
フォアグラウンドっていう状態はないみたいですね。たしかApplicationDelegateにapplicationWillEnterForegroundっていうのがあったはずですが、あれはフォアグラウンド状態に遷移するときに呼ばれるんじゃないんでしょうか。
そうなんです。フォアグラウンドっていう状態はないんです。このへん、自分でもよくわからなくなったので、あちこち調べて理解したのですが、最近人に聞かれる機会があったので図にしてみました。
IOS4以降のアプリ状態遷移図
ログ入れて実機(iPhone4)で調べたので実際の動作と同じになっていると思います。(間違いあったらご指摘お願いします)
図中、起動系は赤、終了系は青の線と色分けしています。
先程のフォアグラウンドの件、これがフォアグラウンドだという明確な記述は見つけられませんでしたが、たぶんACTIVEかINACTIVEかのどちらかにいる時をフォアグラウンドといってるっぽいですね。
ローカル通知はどう受け取るか
どういうときに状態遷移を理解していると便利かという事例として、時刻がくると発報するローカル通知を使ったアプリを作っている時に、通知イベントの動作で困ったことがありましたのでそれを紹介します。
通常、ローカル通知イベントが発生するとアラートウィンドウが出ますが、アプリが動いている(わざとあいまいな表記をしています)時に発生したローカル通知イベントは、アラートウィンドウを出さずにApplicationDelegateに通知されます。アプリからは、アラートウィンドウが出たかどうかを知る手段がないんです。
そこでログを入れて調べていますと
- アラートウィンドウが出るパターン (メソッド名は一部省略しています)
- アラートウィンドウが出ないパターン
となっていました。どうやらNotify通知を受け取るのがapplicationDidBecomeActiveの前か後かによって判別できそうです。フラグをBecomeActive時にYES、ResignActive時にNOになるフラグを作って、フラグがYESの時は自力でアラートウィンドウを出すという対策を施しました。
でも、すべての場合についてこれで良いかどうか確信が持てません。こういう時はテストして調べることになるのですが、すべての状態を網羅しないと完全とは言えません。
このような場合に状態遷移図を見てテストケースを決めるわけです。
今回の場合は、メールなどのアラートを出していたりするときのNotify通知のテストが漏れていることがわかりました。(ちゃんと動きました)
参考になれば幸いです。