iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど
iOS6から導入された状態の保存と復元を試してみた。この状態の保存と復元は多くのパターンがあるのだが、今回のその一部のみだ。
UIKitの状態保存システムは、バックグラウンド実行しているアプリケーションが、リソース不足等の理由からOSによって停止させられた場合に、フォアグラウンド状態となった際に、停止前の状態を再現する機能のようだ。なので、ユーザが強制的に停止させた場合は、対象で機能しないらしい。
保存と復元の対象はビューコントローラで、ビューコントローラとその配下のビューの状態が保存と復元される。そして、モデルについては対象としないようにするのが利用するコツのようだ。
状態の保存と復元の対応によって、たとえば、アプリケーション・デリゲートのメソッドは、呼ばれるタイミングが、保存と復元の前なのか、後なのかを意識する必要がある。
/* 状態情報復元前の初期化 */
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
DBGMSG(@"%s", __func__);
[[Document sharedDocument] load];
return YES;
}
/* 状態情報復元後の初期化 */
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
DBGMSG(@"%s", __func__);
return YES;
}
/* 状態情報保存前のモデル保存 */
- (void)applicationWillResignActive:(UIApplication *)application
{
DBGMSG(@"%s", __func__);
[[Document sharedDocument] save];
}
この機能を有効化は、アプリケーションのデリゲートで行われる。
/* 状態情報保存の有効化 */
- (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder
{
return YES;
}
/* 状態情報復元の有効化 */
- (BOOL)application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder
{
return YES;
}
Storyboardで、ビューコントローラにRestoration IDというのが追加されているのが確認できるが、このIDで保存と復元が行われる。同じビューコントローラが複数生成され、それを区別する場合は、インスタンス毎にIDを変える等の工夫が必要なようだ。
ビューコントローラの状態の保存と復元は、その為のメソッドを実装する。
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
NSLog(@"MasterViewController: encodeRestorableStateWithCoder");
[super encodeRestorableStateWithCoder:coder];
[[Document sharedDocument] save];
[coder encodeInteger:self.detailItemIndex forKey:kUnsavedDetailItemIndexKey];
}
- (void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
NSLog(@"MasterViewController: decodeRestorableStateWithCoder");
[super decodeRestorableStateWithCoder:coder];
self.detailItemIndex = [coder decodeBoolForKey:kUnsavedDetailItemIndexKey];
[self configureView];
}
上記の例では、配列型のモデルのインデックスを保存していて、復元時は、そのインデックスで停止前のデータにアクセスするようにしている。
実際に動作確認したいのだが、どうやったら、OSによって停止させられるのかよく分からなかった為。これで上手くいくのは、まだ試していない。残念!