3

現在、FRCのfetchRequestのfetchLimitが4の場合、NSFetchedResultsControllerを使用するUITableViewController / UITableViewが約86個のアイテムを表示するという問題が発生しています。86個のアイテムがフェッチ自体を満たしていること、およびそれらが表示される理由を知っています。これは、didChangeObject:atIndexPath ...が86のそれぞれに対して呼び出され、デフォルトの実装の一種として挿入するためです。

私の質問は、fetchLimitがNSFetchedResultsControllerが「変更」(この場合は挿入)しようとするオブジェクトの数を制限しないのはなぜですか?

私のアプリケーションのユースケースは、最初のタブに、アプリの起動時に(サイドスレッドで)取得する一般的なフィードアイテムが表示されることです。それらを別のコンテキストのCoreDataに保存します。これは、最終的にメインスレッドのコンテキストにマージされ、変更された内容に対してFRCコールバックを開始します。私の質問は、特にアイテムが存在しない最初のケースに関するものです。


これが私のfetchRequestです:

    NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];
fetchRequest.entity = [NSEntityDescription entityForName:ENTITY_CONTENT_ITEM inManagedObjectContext:managedObjectContext];

// Set a limit on the number of items returned
[fetchRequest setFetchLimit:4];

// Set a Predicate to limit the fetch to featured items only
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"featured == YES AND contentType == %d", contentType]];

// Set the sort descriptors
NSSortDescriptor *sortDateDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"sortDate" ascending:NO] autorelease];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDateDescriptor]];

上記のcontentTypeは、このタブに表示されるはずのものと他のタブに表示されるものを区別するための単なる方法です。アイテムのブールプロパティが注目されています。これは、表示用のオンオフスイッチのようなものです。

これが私のdidChangeObjectです:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { 
  switch(type) {
    case NSFetchedResultsChangeInsert:
      [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
      break;
    case NSFetchedResultsChangeDelete:
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
      break;
    case NSFetchedResultsChangeUpdate:
      [tableView cellForRowAtIndexPath:indexPath];
      break;
    case NSFetchedResultsChangeMove:
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
       // Reloading the section inserts a new row and ensures that titles are updated appropriately.
       [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
       break;
  }
}

この質問に答えるのは難しいでしょうが、FRCがdidChangeObjectを呼び出す回数を決定する方法の説明でさえ本当に役に立ちます。

4

1 に答える 1

1

https://devforums.apple.com/thread/60319?tstart=0

これにアクセスできる人は、チェックしてください。アップルの開発者は、iOS4.0のCoreData / NSFetchedResultsController/UITableViewControllerスタックへの変更の概要を簡単に説明します。

キャッシュとパフォーマンスを改善し、既知の問題を修正するために、3.2と4.0で変更が加えられました。永続キャッシングははるかに積極的であるため、cacheNameを誤用する人々は問題にぶつかりました。代わりにcacheNameをnilに設定するか、使用法をクリーンアップして、必要に応じて+deleteCacheWithNameを呼び出すことが解決策です。セクションの再計算が改善され、可能な限りメモリ内ではなくデータベースを介してより多くの計算を実行できるようになりました。キャッシュが再構築されるたびに(または、キャッシュを使用しない場合は、performFetchが呼び出されると)、セクショニングがトリガーされます。.descriptionの回避策により、キーパスはモデル化されていないプロパティ(-descriptionメソッド)を参照します。これにより、dbは-descriptionについて何も認識しないため、代わりにセクション計算がメモリ内で機能します。

4.0では、UITableViewに変更が加えられ、UITableViewControllerデリゲートコールバックに関連する多くの問題が修正されました。トラブルを回避するために以前のiOSリリースで-reloadDataを使用する必要があった人は、iOS4でよりきめ細かいコールバックを使用できるはずです。

-BenT(アップル)

それを前提として、fetchedResultsControllerinitWithFetchRequest呼び出しのsectionNameKeyPathに.descriptionを追加しました。これにより、セクションの計算がディスクではなくメモリで行われるようになり、セクションのアイテム数が実際よりも多いと考えるセクションの問題が修正されました。

これは4.0で機能し、3.0ではcontrollerDidChangeContentコールバックからreloadDataを呼び出すだけです。同様の問題が発生した場合は、遠慮なく私にメッセージを送ってください。

于 2010-07-27T20:11:44.440 に答える