3

我有一个 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 getter 做了正确的事:

- (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 中“切换”数据,其中“切换”意味着具有不同的谓词,甚至(在我的情况下不是)不同的实体。

请注意,为了完整起见,由于从 Selection 到 Document 的多对多关系是有序的,因此它是通过称为 DocInSelection 的中间轻量级实体处理的,该实体具有“排序”属性和两个多对一与文档和选择的关系。

感谢您的任何建议。

4

4 回答 4

15

由于 NSFetchedResultsController(FRC) 是一个对象,因此您可以像存储任何其他对象一样存储它的实例。

一种有用的技术是在字典中初始化和存储几个 FRC,然后将 tableview 控制器的fetchedResultController属性设置为您现在需要的 FRC。这对于使用分段控件对同一表中的不同属性或实体进行排序等情况很有用。这种技术的优点是可以维护单独的 FRC 缓存,这可以显着加快获取速度。

只需确保beginUpdates在交换控制器之前发送 tableview 本身,然后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 类参考

iOS 3.2 参考库中不存在此附加说明。

只是想指出这一点。

于 2010-09-16T13:25:06.957 回答
0

一个重要的注意事项:如果你“覆盖”一个 fetchController 对象,请确保你首先清除它的 .delegate - 否则你会在删除行时崩溃,等等,因为旧的 fetchController 及其委托获取事件。

于 2011-05-03T13:47:24.440 回答