UIViewController - 状態保存復元パターン

2010年8月5日木曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

状態の保存と復元


他の UIViewController を呼び出したり、ピッカーを表示した時にメモリ不足が発生すると呼び出し元のビューが開放される。元の画面に戻った時に自動的にビューが再作成されるのだが、この時画面遷移前の状態を保存しておく必要のあるケースが多い。例えば、一覧画面で検索を行いその詳細画面を表示するケース。詳細画面から戻った時には直前の検索条件を保っておく必要がある。また UITableViewで編集モードに入っていて別画面で項目の編集を行った後に元の画面へ戻るケース。この場合も編集モードの状態で表示されるのが望ましい。ただ、これらの状態の多くはビューが保持している情報なので、ビューが破棄・再作成されると状態が消えてしまう。直前の状態を保つには、これらの状態を UIViewController 側で保存・復元する必要がある。


イベントの流れ


メモリ不足が発生する前に状態を保存し、再びビューが再作成されたタイミングで状態を復元した。これらをどのタイミング(イベント)でやるべきか。それを考える為に前回示した図を再掲する。

MyViewController の画面が消えた後の didDisappear: で状態を保存し、再びビューが作成された後の viewDidLoad で復元するのが良さそうだ。まとめるとこう:
イベント操作
viewWillDisappear:状態の保存
viewDidLoad状態の復元

実際 Appleが提供する次のサンプルでは次のタイミングで保存と復元を行っていた。
TableSearch

このサンプルでは検索条件の保存と復元を行っている。

[参考情報] Cocoaの日々: UISearchDisplayController 調査

コードを引用してみる。まずは保存から。
- (void)viewDidDisappear:(BOOL)animated
{
    // save the state of the search UI so that it can be
    //  restored if the view is re-created
    self.searchWasActive = [self.searchDisplayController isActive];
    self.savedSearchTerm = [self.searchDisplayController.searchBar text];
    self.savedScopeButtonIndex = [self.searchDisplayController.searchBar
         selectedScopeButtonIndex];
}

次に復元。
- (void)viewDidLoad
{
     :
     :
    // restore search settings if they were saved in didReceiveMemoryWarning.
    if (self.savedSearchTerm)
    {
        [self.searchDisplayController setActive:self.searchWasActive];
        [self.searchDisplayController.searchBar
                setSelectedScopeButtonIndex:self.savedScopeButtonIndex];
        [self.searchDisplayController.searchBar setText:savedSearchTerm];
        
        self.savedSearchTerm = nil;
    }
     :    
     :
}

viewDidDisappear で検索中であることを表すフラグや検索キーワード、スコープなどを保存し、viewDidLoad でそれらを復元している。なお viewDidLoad は一番最初の初期処理でも呼び出されるので、このコードでは self.savedSearchTerm をチェックして必要な時だけ復元を行うようにしている。

他に保存が必要なものとしては UITableView.editing などが考えられる。


動作確認の方法


別の画面を表示している時に iPhoneシミュレータの「メモリ警告をシミュレート」を使うと良い。

[参考] Cocoaの日々: 「メモリ警告をシミュレート」で didReceiveMemoryWarning を擬似的に発生

これを使うとメモリ不足がシミュレートされ、元の画面で didReceiveMemoryWarning、viewDidUnload と呼び出される。その後、元の画面へ戻ると viewDidLoad、viewWillAppear と呼び出される。

Responses

Leave a Response

人気の投稿(過去 30日間)