设置新谓词后NSFetchedResultsController未正确刷新

时间:2015-09-16 21:36:18

标签: ios uitableview core-data nsfetchedresultscontroller nsfetchrequest

我的fetchedResultsController最初是这样创建的(在viewDidLoad中):

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
                               entityForName:@"Cat" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];

NSSortDescriptor *sort = [[NSSortDescriptor alloc]
                          initWithKey:@"age" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];

NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                    managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"age"
                                               cacheName:@"whatever"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;

这很好用,结果显示在我的表视图中。但是,按下某些按钮时我想过滤结果。所以我这样做:

NSPredicate *predicate = ...; //based on buttons pressed


[[self.fetchedResultsController fetchRequest] setPredicate:predicate];
[NSFetchedResultsController deleteCacheWithName:@"whatever"];

NSError * error = nil;
[self.fetchedResultsController performFetch:&error];
if (error) {
    DDLogError(@"[%@ %@] fetchedResultsController ERROR: %@", THIS_FILE, THIS_METHOD, error.localizedDescription);
}
[self.myTableView reloadData];

问题是表视图没有重新加载。如果我滚动表格视图,单元格会根据新数据进行更改,但每次尝试过滤时,部分和行数都不会改变。

我错过了什么?

2 个答案:

答案 0 :(得分:1)

您需要在对fetchResultController进行任何更改之前删除缓存

来自apple doc:NSFetchedResultsController Class Reference

  

如果您正在使用缓存,则必须先调用deleteCacheWithName:   更改任何获取请求,其谓词或其排序   描述。您不能重复使用相同的获取结果控制器   除非您将cacheName设置为nil。

     

(可选)控制器应使用的缓存文件的名称   (传递nil可以防止缓存)。使用缓存可以避免开销   计算部分和索引信息。

答案 1 :(得分:0)

我怀疑您需要根据更新的数据插入和删除表格视图行。

您在其他答案的评论中写的错误消息保留了线索。

相关Apple documentation

您应该具体阅读的内容是标题下的文字: 行和部分的批量插入,删除和重新加载

然而,在此之前,当您更改NSFetchedResultsController时,应检查是否实现了NSFetchedResultsController委托方法来管理更改。 Apple提供的标准代码应包括在表视图控制器中。您不需要更改/覆盖此标准代码。

请参阅此Apple documentation

基本上对于“典型使用”案例,您需要实现四种典型的委托方法:

  • (void)controllerWillChangeContent:(NSFetchedResultsController *)controller;
  • (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo;
  • (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath;
  • (void)controllerDidChangeContent:(NSFetchedResultsController *)controller

的情况下,您已经包含了这些NSFetchedResultsController委托方法,您可能需要考虑使用UITableView委托方法beginUpdatesendUpdates方法: / p>

- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;

所以你应该尝试使用以下代码块:

tableView.beginUpdates;
tableView.insertRowsAtIndexPaths:indexPaths withRowAnimation:animation;
tableView.deleteRowsAtIndexPaths:indexPaths withRowAnimation:animation;
tableView.endUpdates

您显然需要为insert和delete方法创建indexPaths数组。