CoreData: record を追加したのに一覧画面に表示されないぞ?の場合

久しぶりに自分のプログラムを書ける。二ヶ月ぶりぐらいか?前どこでハマっていたのかわかんなくなっちゃった。とりあえず build して状況確認。ああ、そうだ、tableView で + ボタンを押しても record が追加されていない、というか、再度起動すると追加されているのですが、+ ボタンを押した直後、一覧画面にぴょこっと追加されていないぞ?というとき。

ハマりましたね・・・tab で 3 画面作っていて 1 画面だけに起こる現象なのでなんかおかしいぞと。他の画面と見比べれば良いのですが、めんどくセーと思いつつ丹念に見比べました。

結局のところ、NSFetchedResultsControllerDelegate のdelegate method を実装したらちゃんと表示されました。具体的には、以下の通り。

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller

{

    [self.tableView beginUpdates];

}

 

- (void)controller:(NSFetchedResultsController *)controller

  didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo

           atIndex:(NSUInteger)sectionIndex

     forChangeType:(NSFetchedResultsChangeType)type

{

    switch( type )

    {

        case NSFetchedResultsChangeInsert:

            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];

            break;

            

        case NSFetchedResultsChangeDelete:

            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];

            break;

            

        default:

            return;

    }

}

 

 

- (void)controller:(NSFetchedResultsController *)controller

   didChangeObject:(id)anObject

       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type

      newIndexPath:(NSIndexPath *)newIndexPath

{

    UITableView *tableView = self.tableView;

    

    switch(type) {

        case NSFetchedResultsChangeInsert:

            [tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];

            break;

            

        case NSFetchedResultsChangeDelete:

            [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

            break;

            

        case NSFetchedResultsChangeUpdate:

            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] withEvent:anObject];

            break;

            

        case NSFetchedResultsChangeMove:

            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] withEvent:anObject];

            [tableView moveRowAtIndexPath:indexPath toIndexPath:newIndexPath];

            break;

    }

}

 

特に、

- (void)controller:(NSFetchedResultsController *)controller

   didChangeObject:(id)anObject

       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type

      newIndexPath:(NSIndexPath *)newIndexPath

 

が重要で、CoreData に変更があったとき、tableView に反映するため呼ばれるのだと。よく似たその上の method は、section の反映。

やっぱり CoreData は鬼門。