Posts Tagged ‘Core Date’

Master-Detail Appで新規追加画面から戻るとUITableViewに空のセルが追加されてしまう


 Xcodeでプロジェクトを作成する時に選べるテンプレートの中に「Master-Detail Application」というのがある。これはいわゆる一覧画面と詳細画面を行き来する割と代表的なアプリケーションの形であり、頻繁に利用されるパターンでもある。一覧と詳細と言えば、その多くがデータベースのようなものと組み合わせて使うのが一般的だ。ローカルのデータベースの場合、特にこだわりがなければCoreDataを使う事になると思うが、その際にちょっとハマったケースがあるのでメモしておく。

 それは詳細画面というより編集画面を新規追加の局面で開いた場合だ。ところで「Master-Detail Application」ではUITableViewControllerの他にUINavigationControllerが使われているので、編集画面にて保存の操作を行うにはUINavigationBarに保存ボタンを追加し、NSManagedObjectContextオブジェクトのsaveメソッドを呼ぶ事で保存を行うことができる。ただ、編集画面を新規追加で開いた瞬間にNSManagedObjectクラスのインスタンスが生成されるようで、保存せずに戻るボタンが押された場合には一覧画面に空のセルが追加されてしまう。これを防ぐには戻るタイミングで未保存の変更がある場合には、以下のようにロールバックするコードを書けば良い。

1
2
3
4
5
- (void)viewWillDisappear:(BOOL)animated {
    if ([self.managedObjectContext hasChanges]) {
        [self.managedObjectContext rollback];
    }
}

 これで空のセルが追加されるのを防ぐ事ができる。

UITableViewの一覧にCora Dataで取得した内容を反映する


 Core Dataのサンプルとか、UITableViewのサンプルとかはネット上でも書籍でもかなり豊富にあるのだが、それらの組み合わせの例は意外と少ない。先日見つけた書籍はかなり詳しく書いてあって「これはいけるか!?」と思われたが、実は肝心なコードが抜けていた。それはMaster-Detail型で言うところのMaster画面でCore Dataから取得したデータの一覧をUITableViewに表示する際、一覧の見出しにデータの内容が反映されないのだ。おそらくその書籍の著者にとってはあまりに自明の事なので記載するのを忘れてしまったのだろう。あるいはそれくらいは自分で考えろという事なのかもしれない。

 まあここで毒づいても仕方が無いので対処方法をメモしておく。

 一覧に内容を反映させるには MasterViewController.m の 
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
メソッドにコードを記述する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell;
    // iOSのバージョンによりセルの取得方法が変わる
    if (6.0 <= [[[UIDevice currentDevice] systemVersion] floatValue]) {
        cell = [tableView dequeueReusableCellWithIdentifier:@"AnyId" forIndexPath:indexPath];
        [self configureCell:cell atIndexPath:indexPath];
    }
    else {
        cell = [tableView dequeueReusableCellWithIdentifier:@"AnyId"];
        if (!cell) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"AnyId"];
        }
    }
    // ここでセルの表示を変更
    NSManagedObject* managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = managedObject.anyProperty;
    return cell;
}


 尚、iOSのOSバージョンを判別する方法は以下のサイトを参考にした。
http://syszr.com/s14.html

“The model used to open the store is incompatible with the one used to create the store” に対処する


Core Dataを使った開発をしていたら次のようなエラーが出てシミュレータで起動しなくなったので、対処方法をメモしておく。

The model used to open the store is incompatible with the one used to create the store

プロジェクトをクリーンしてもダメで、このエラーメッセージで検索したところ、sqliteのファイルを削除しないとダメなのだそうだ。
そのsqliteファイルは以下の場所。ターミナルを開いてrmコマンドで削除する。

/Users/{ユーザー名}/Library/Application Support/iPhone Simulator/{iOSバージョン}/Applications/{英数字}/Documents/{プロジェクト名}.sqlite

参考にしたページはこちら
http://u2k772.blog95.fc2.com/blog-entry-167.html

アーカイブ