我有一个UITableView,它显示了使用CoreData存储的对象列表。我可以使用以下代码删除对象:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSLog(@"Delete row");
[managedObjectContext deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]];
// Save the context.
NSError *error;
if (![managedObjectContext save:&error]) {
/*do this gracefully one day */
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
[self refreshTables]; //where refreshTables just reloads the data the table is using and calls [self.tableView reloadData];
}
}
但它没有动画或美学。
当我尝试通过替换
进行动画制作时[self refreshTables];
带
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
我收到以下错误:
断言失败 - [UITableView _endCellAnimationsWithContext:],> /SourceCache/UIKit_Sim/UIKit-1261.5/UITableView.m:920 2010-10-30 16:46:35.717 MyApp [38226:207] * 由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'无效更新:第0节中的行数无效。更新(3)后现有部分中包含的行必须等于更新前该部分中包含的行数(3),加上或减去从该部分插入或删除的行数(0插入,1删除)。“
我已尝试在commitEditingStyle代码中的各个位置使用 deleteRowsAtIndexPaths 代码而没有运气(例如在从mOC中删除对象之前)但我似乎无法绕过这个错误。
我知道Apple的iPhoneCoreDataRecipes示例通过设置FetchedResultsController的委托处理编辑/删除行来处理问题,但是在开发的这个阶段,如果可能的话,我只想要一个简单的解决方案来动画那些删除的对象。
如何在从managedObjectContext中删除对象之前/之后动画删除行?
编辑:我在从mOC中删除项目之前和之后尝试使用deleteRowsAtIndexPaths,但出现了相同的错误。
答案 0 :(得分:17)
当我们使用NSFetchedResultsController作为UITableView的DataSource时,我们无法在函数deleteRowsAtIndexPaths: withRowAnimation:
中调用tableView: commitEditingStyle: forRowAtIndexPath:
,这将引发异常问题。
解决此问题的一种方法是从协议[self.tableView reloadData]
中调用controllerDidChangeContent:
中的NSFetchedResultsControllerDelegate
。它实际上解决了,不再有删除淡入淡出动画。
因此,另一种方便的方法是在[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]
中调用controller: didChangeObject: atIndexPath: forChangeType:
newIndexPath:
。
示例代码如下:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
// Delete NSManagedObject
NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
[context deleteObject:object];
// Save
NSError *error;
if ([context save:&error] == NO) {
// Handle Error.
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
if (type == NSFetchedResultsChangeDelete) {
// Delete row from tableView.
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
}
答案 1 :(得分:7)
1)我设置了一个正确的代表。
2)我在viewWillLoad中删除了一个调用[self.tableview reloadData];这是(奇怪的)弄乱了一切(这篇文章给了我一个线索,寻找和删除:Serious Application Error in Core Data with fetchedResultsContainer)。
答案 2 :(得分:0)
您是否正在使用NSFetchedResultsController?
您收到此错误,因为该对象仍在您的tableview数据源中。
也许at this stage in development
您正在使用simple solution
并使用来自NSFetchRequest的对象填充NSArrays。那么从托管对象上下文中删除对象
您是否正在为NSFetchedResultsController使用缓存?我刚刚在文档中再看一下,发现了这个:
控制器因此有效地具有 确定了三种操作模式 是否有代表和 是否设置了缓存文件名。
无跟踪:委托设置为 零。控制器只是提供 访问数据时的情况 fetch已执行。
仅内存跟踪:代表是 非nil和文件缓存名称已设置 没有。控制器监控 结果集和更新中的对象 部分和订购信息 对相关变化的回应。
完全持久跟踪:代表 并且文件缓存名称是非零的。 控制器监视其中的对象 结果集和更新部分和 订购信息以响应 相关变化。控制器 维护一个持久的缓存 计算结果。
因此控制器的模式是“无跟踪”。这意味着如果从托管对象中删除对象,则不会从控制器中删除对象
just reloads the data
代码中refreshTables
的含义是什么?在删除行之前尝试执行相同的操作
或者添加使代表工作所需的20行。
答案 3 :(得分:-2)
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSLog(@"Delete row");
// Delete the row first
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
//Then delete the object.
[managedObjectContext deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]];
// Save the context.
NSError *error;
if (![managedObjectContext save:&error]) {
/*do this gracefully one day */
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}