CoreDataのNSFetchedResultsControllerに関するメモ

NSFetchedResultsController の挙動について少しまとめます。
UITableView で CoreData のデータを利用するときに使うクラスです。

初期化

まず NSFetchedResultsController の初期化方法

  • fetchRequest
    • View に表示するためのデータを取得するための NSFetchRequest を指定
    • NSFetchRequest に NSSortDescriptor は必ず指定しないといけない
  • context
    • データの取得、変更の監視を行う NSManagedObjectContext を指定
  • sectionNameKeyPath
    • セクションを指定するときに指定する。
  • cacheName
    • fetch した結果をディスクにキャッシュするかどうか
    • キャッシュしない場合は、nil を指定

デリゲートメソッド

UITableView 上でのデータの挿入、更新、削除、移動イベントに対して、何か独自の処理を行いたいときは、NSFetchedResultsController にデリゲートをセットします。

NSFetchedResultsController のインスタンスに delegate を指定すると、以下のデリゲートメソッドが呼ばれる。

デリゲートメソッドの実装方法

以下がデリゲートメソッドの実装方法です。ほとんどAppleのサンプルコードと同じです。
NSFetchedResultsChangeUpdate の時だけちょっと実装を変えています(理由は こちら)。
例えば、新しいデータがインサートされてきた時に、ダウンロード処理をフックするとか、独自の処理をここに記述できます。

デリゲートメソッドが呼ばれるタイミング

controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: が呼ばれるのは、初期化時に指定した context に変化があった時です。変化というのは以下の3種類。

  • NSFetchedResultsChangeInsert
    • [NSEntityDescription entityForName:inManagedObjectContext:] が実行された時
  • NSFetchedResultsChangeUpdate
    • NSManagedObject のインスタンスに値が代入された時
    • ※インスタンスが保持している値と代入する値が全く同じでも、デリゲートが呼ばれます
    • ※セルにアニメーションを仕込んでいるときは要注意(セルがリロードされて何度もアニメーションが発生してしまうので)
  • NSFetchedResultsChangeDelete
    • [NSManagedObjectContext deleteObject:] が実行された時

NSManagedObject の変化がまとめてこのデリゲートメソッドに通知されます(controllerWillChangeContent: と controllerDidChangeContent: が1回呼ばれる間に、 複数 controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: が呼ばれる)。[NSManagedObjectContext save:] を呼び出した時に、NSManagedObjectContextDidSaveNotification の通知が飛ばされます。NSFetchedResultsController は内部的にこの通知を購読していて、この通知を受け取った時に、これらのデリゲートメソッドを呼び出しているのではないかと思います。

複数の変化がまとまってやってくるので、非同期処理とかここで行う場合は要注意です。
controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: で渡ってくる indexPath のセルと非同期処理のコールバックで戻ってきた時に処理を行うセルがミスマッチしていて、適切に更新できない場合があります。

キャッシュ

キャッシュを使うかどうかは、NSFetchedResultsController の初期化時点で指定することができます。
キャッシュを使うことで、NSManagedObject と UITableView の indexPath の対応を再計算するコストを回避できます。キャッシュを利用する際の注意点について。私はこのキャッシュについてあまり理解せず使っていて、ちょっとハマりました。。

  • 複数の NSFetchedResultsController で同じキャッシュを利用していけない。キャッシュ名はしっかり分ける。
  • NSFetchRequest の predicate や sortDescriptors が変わった場合、fetchedResultsController を呼び出す前に、deleteCacheWithName: を呼び出して、キャッシュをクリアする必要がある。

NSFetchedResultsController v.s. NSFetchRequest

ただ単に CoreData からデータを取得したいだけなら、NSFetchedResultsController を使う必要はないです。
以下のように、NSFetchRequest を使うことで、クエリの実行が可能です。

リンク

iOS Core Data徹底入門
iOS Core Data徹底入門

posted with amazlet at 14.01.01
國居 貴浩
秀和システム
売り上げランキング: 12,185