iOS 4でのFast App Switchingの導入により、iOSアプリのライフサイクルは若干複雑になりました。今更ではありますが、アプリケーションの終了のフックについて調べたのでまとめておきます。
applicationWillTerminate
UIApplicationDelegateには元々applicationWillTerminate:というメソッドがあり、このメソッドはアプリケーションが終了される直前に呼ばれます。
- (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. NSLog(@"Application will terminate."); }
Fast App Switchingを無効(Application does not run in backgroundをYES)にした状態でアプリケーションを実行し、ホームボタンを押すとログにApplication will terminate.が出力され、メソッドが呼び出されたことが確認できます。
TerminationTest[4111:c07] Application will terminate.
Fast App Switching対応アプリの場合
一方、Fast App Switchingを有効にしているアプリではホームボタンを押してアプリをバックグラウンドに移行しても、アプリ自体はまだ終了しないのでapplicationWillTerminateは呼び出されません。
UIApplicationDelegate Protocol Referenceには、Fast App Switching有効時のapplicationWillTerminateメソッドの挙動について、下記の用な説明があります。
For applications that support background execution, this method is generally not called when the user quits the application because the application simply moves to the background in that case. However, this method may be called in situations where the application is running in the background (not suspended) and the system needs to terminate it for some reason.
アプリケーションがバックグランドで動作してる途中で終了される場合は呼び出されるかもしれないけど、サスペンド状態から終了される場合は呼び出されない、ようです。
バックグラウンドに移行したアプリをホームボタン長押しで表示される最近起動したアプリ一覧から終了すると、その時点でデバッガとの接続が切れてしまいログの出力を確認できないため、ログの代わりにNSUserDefaultsを使ってapplicationWillTerminate:イベントが呼ばれているか確認するコードを書いてみます。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { ... [[[UIAlertView alloc] initWithTitle:@"RESULT" message:[NSString stringWithFormat:@"%@", [[NSUserDefaults standardUserDefaults] objectForKey:@"a"]] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; return YES; } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"a"]; [[NSUserDefaults standardUserDefaults] synchronize]; }
この状態でアプリの実行・終了を繰り返してみましたが、applicationWillTerminate:が呼ばれることはありませんでした。
結論:Fast App Switching対応アプリではapplicationDidEnterBackgroundを使う
ドキュメント、コメントにもあるように、Fast App Switching対応アプリではアプリケーション終了時にやりたいような処理はapplicationWillTerminate:ではなくapplicationDidEnterBackground:内で行う方が良さそうです。