我有一个NSFetchedResultsController,它在UITableView中显示数据。在选择创建核心数据项目时,我使用Xcode提供的锅炉板代码。我在NSFetchedResultsController使用的NSFetchedResultsController中添加了以下谓词(在初始化NSFetchedResultsController之前):
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"deleted == NO"];
[fetchRequest setPredicate:predicate];现在,在我的应用程序的另一个位置,我设置了以下删除属性(伪代码):
myManagedObject.deleted = YES
saveDataContext当我返回到TableViewController时,它仍然显示这个“删除”行。
当我尝试重新加载表视图时,什么都不会发生。
当我尝试使用fetchedResultsController重新加载performFetch时,它说:
‘致命错误:区段信息的持久缓存与当前配置不匹配。您非法地修改了NSFetchedResultsController的获取请求、谓词或排序描述符,而没有禁用缓存或使用+删除deleteCacheWithName:’
如果我删除缓存,在init方法中调用performFetch,然后调用[myTable reloadData] --它可以工作。
难道没有更简单的方法来刷新数据吗?最好是允许您使用NSFetchedResultsController的缓存特性?
据我所知,我修改fetch请求、谓词或排序描述符的唯一位置是在分配和在NSFetchedResultsController中分配相同的方法中,因此它显示的错误消息似乎是不正确的。
更新:既然我对NSFetchedResultsController有了更好的理解,我就知道它不会自动删除行,而主要负责删除行的是controller:didChangeObject:atIndexPath:forChangeType:nowIndexPath:方法。我已经实现了这个方法,因为我在我的项目中使用了Apple的模板。
但是,在我的例子中,我实际上不是删除一个项,我只是更新一个属性(deleted),以指定该项不应该再存在于列表中。这意味着controller:didChangeObject:atIndexPath:forChangeType:nowIndexPath:方法的更改类型是NSFetchedResultsChangeUpdate而不是NSFetchedResultsChangeDelete。我将代码更新为如下内容:
case NSFetchedResultsChangeUpdate: {
MyObj *obj = (MyObj *)anObject;
if (obj.deletedValue) { // NOTE: deletedValue returns the deleted property as BOOL
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else {
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
}
}问题是,我得到了错误消息:
无效更新:第0节中的无效行数。更新(3)之后包含在现有节中的行数必须等于更新(3)之前包含在该节中的行数,加上或减去从该节插入或删除的行数(1插入,2删除)。使用userInfo (null)
基本上,这是抱怨NSFetchedResultsController中的对象数和表中的单元格数没有同步。
希望这能使它更清楚:
// DB Items (Name, Deleted):
[Foo, NO]
[Bar, NO]
[Baz, NO]
// mark one as deleted
Objects[1].deletedValue = YES;
// DB items now look like so:
[Foo, NO]
[Bar, YES]
[Baz, NO]即使NSFetchedResultsController的NSFetchRequest的NSPredicate设置为deleted == NO,NSFetchedResultsController仍然可以看到3项而不是2项。
我怎样才能解决这个问题?我需要以某种方式刷新NSFetchedReultsController吗?还有什么问题吗?
发布于 2010-10-30 00:41:52
问题是,在这种情况下,我没有意识到deleted是一个保留字。我不得不重新命名这片土地,它运转得很好。
发布于 2010-10-06 13:32:43
您需要设置到NSFetchedRequestController的委托,以便跟踪更改。要处理批处理更新,您需要覆盖三个方法:
controllerWillChangeContent: -(索引路径的设置列表here)controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: -)(为每个调用存储here)controllerDidChangeContent: (在这里对UITableView进行异常更新)对于一个简单得多的情况,在这种情况下,您知道每次只更新一个行,然后进行如下操作:
-(void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath;
{
switch (type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationTop];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationTop];
break;
case NSFetchedResultsChangeUpdate:
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}发布于 2010-10-06 10:42:28
在我看来,从错误消息中可以很清楚地看到,NSFetchedResultsController不希望您在创建它的提取请求后更改它。
您需要做的是在初始化NSFetchedRequestController之前将谓词添加到提取请求中。如果您想在应用程序运行时更改fetch请求的谓词,您可能需要创建一个新的NSFetchedRequestController并完全替换旧的。
https://stackoverflow.com/questions/3869433
复制相似问题