3

「Documents」という名前の多数のエンティティのサブセットを表示するUITableViewがあります。サブセットは、別のエンティティ「選択」によって定義されます。選択範囲には、名前が付けられた、順序付けられたドキュメントのリストがあります。

実行時に表示される選択を変更したい場合を除いて、正常に動作します。空白のリストしか表示されません。

基本的に、新しい述語が別の選択を使用するように、NSFetchedResultsControllerが保持する述語を変更する必要があります。私はそれを機能させることができませんでした。私の最後の試みは、NSFetchedResultsControllerを完全に取り除き、それを再割り当てすることです。

- (void) displaySelection:(Selection *)aSet
{
 self.currentSelection = aSet;
 self.fetchedResultsController = nil;
 // methods here don't all use the property but directly the ivar, so we must trigger the getter
 [self fetchedResultsController];
 [self.tableView reloadData];
}

そしてもちろん、NSFetchedResultsControllerゲッターは正しいことをします:

- (NSFetchedResultsController *)fetchedResultsController
{
    if (fetchedResultsController != nil) { return fetchedResultsController; }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"DocInSelection" inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"selection.identifier like %@", currentSelection.identifier];
    [fetchRequest setPredicate:predicate];
<snip>
    [fetchRequest setSortDescriptors:sortDescriptors];
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;
<snip>
    return fetchedResultsController;
}

初期選択が設定されているため、このコードは初めて機能します。ただし、がdisplaySelection:呼び出されると、テーブルビューは空白になります。

NSFetchedResultsControllerフェッチリクエストで非常によく似た質問がありました-述語とUITableViewの更新

そしてその答えは、NSFetchedResultsControllerを取り除くことでした。NSFetchedResultsControllerは、ここに多くの便利な機能(キャッシュ、部分的な読み込みなど)をもたらすため、これは行いたくありません。問題はまだ残っています。NSFetchedResultsControllerに基づくUITableViewのデータを「切り替える」方法です。ここで、「切り替える」とは、別の述語、または(私の場合は)別のエンティティを持つことを意味します。

完全を期すために、選択からドキュメントへの多対多の関係は順序付けられているため、「順序付け」プロパティと2つの多対1を持つDocInSelectionと呼ばれる中間の軽量エンティティを介して処理されることに注意してください。ドキュメントと選択との関係。

提案をありがとう。

4

4 に答える 4

15

NSFetchedResultsController(FRC)はオブジェクトであるため、他のオブジェクトと同じようにそのインスタンスを格納できます。

便利な手法の1つは、いくつかのFRCを初期化してディクショナリに格納してから、テーブルビューコントローラのfetchedResultController属性を現時点で必要なFRCに設定することです。これは、セグメント化されたコントロールを使用して、同じテーブル内のさまざまな属性またはエンティティで並べ替える場合などに役立ちます。この手法には、フェッチを大幅に高速化できる個々のFRCキャッシュを維持できるという利点があります。

beginUpdatesコントローラを交換する前にテーブルビュー自体を送信し、完了したら必ず送信してendUpdatesください。これにより、FRCがスワップアウトされているときに、テーブルが狭いウィンドウでデータを要求するのを防ぎます。次に、を呼び出しますreloadData

于 2010-08-16T15:46:31.097 に答える
6

質問を投稿した後、他の質問のOPが示したコードの変形を試しました。わたしにはできる。ここにあります:

- (void) displaySelection:(Selection *)aSet
{
    if (aSet != self.currentSelection) {
        self.currentSelection = aSet;

        NSFetchRequest *fetchRequest = [[self fetchedResultsController] fetchRequest];
        NSPredicate *predicate = nil;
        NSEntityDescription *entity = nil;
        entity = [NSEntityDescription entityForName:@"DocInSelection" inManagedObjectContext:managedObjectContext];
        predicate = [NSPredicate predicateWithFormat:@"selection.identifier like %@", currentSelection.identifier];
        [fetchRequest setEntity:entity];
        [fetchRequest setPredicate:predicate];

        [NSFetchedResultsController deleteCacheWithName:@"Root"];

        NSError *error = nil;
        if (![[self fetchedResultsController] performFetch:&error]) {
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }       
    }
    [self.tableView reloadData];
}
于 2010-08-16T15:05:28.263 に答える
3

これはうまくいくかもしれませんが、iOSリファレンスライブラリに私を悩ませているメモがあります:

重要:フェッチ要求を変更しないでください。たとえば、述語やソート順を変更してはなりません。

ソース:NSFetchedResultsControllerクラスリファレンス

この追加のメモは、iOS3.2リファレンスライブラリには存在しません。

これを指摘したかっただけです。

于 2010-09-16T13:25:06.957 に答える
0

重要な注意:fetchControllerオブジェクトを「上書き」する場合は、必ず最初に.delegateをクリアしてください。そうしないと、古いfetchControllerとそのデリゲートがイベントを取得するため、行の削除などでクラッシュが発生します。

于 2011-05-03T13:47:24.440 に答える