2010-10-30 30 views
8

我有一个UITableView,显示与CoreData一起存储的对象的列表。我可以使用下面的代码删除一个对象:使用CoreData在UITableView中动画行删除给出断言失败

- (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.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 

更换

[self refreshTables]; 

动画我得到以下错误:

Assertion failure in -[UITableView _endCellAnimationsWithContext:], >/SourceCache/UIKit_Sim/UIKit-1261.5/UITableView.m:920 2010-10-30 16:46:35.717 MyApp[38226:207] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (3) must be equal to the number of rows contained in that section before the update (3), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted).'

我已经试过具有deleteRowsAtIndexPaths在代码commitEditingStyle代码中的各种地方都没有lu ck(例如,在从mOC中删除对象之前),但我似乎无法解决此错误。

我知道Apple的iPhoneCoreDataRecipes示例通过为FetchedResultsController设置处理编辑/删除行的代理来处理问题,但在开发的这个阶段,如果可能的话,我只需要一个简单的动画处理这些删除对象的解决方案。

如何在从我的managedObjectContext中移除对象之前/之后为动画删除行?

编辑:我试着从mOC中删除项目之前和之后有deleteRowsAtIndexPaths,具有相同的错误。

回答

-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(); 
      } 
     } 


    } 
+0

不,那是行不通的。我在发布之前尝试过。同样的错误:断言失败 - [UITableView _endCellAnimationsWithContext:],/SourceCache/UIKit_Sim/UIKit-1261.5/UITableView.m:92 – glenstorey 2010-10-30 06:36:33

0

您是否在使用NSFetchedResultsController?
你得到这个错误,因为该对象仍然在你的tableview数据源中。

也许at this stage in development您正在使用simple solution并使用NSFetchRequest中的对象填充NSArrays。然后,它会是毫无意义的,从


您使用的NSFetchedResultsController缓存管理对象上下文中删除对象?我刚刚看了一下文档,发现:

A controller thus effectively has three modes of operation, determined by whether it has a delegate and whether the cache file name is set.

No tracking: the delegate is set to nil. The controller simply provides access to the data as it was when the fetch was executed.

Memory-only tracking: the delegate is non-nil and the file cache name is set to nil. The controller monitors objects in its result set and updates section and ordering information in response to relevant changes.

Full persistent tracking: the delegate and the file cache name are non-nil. The controller monitors objects in its result set and updates section and ordering information in response to relevant changes. The controller maintains a persistent cache of the results of its computation.

所以控制器的模式是“没有跟踪”。这意味着如果从管理对象中删除对象,则不会从控制器中删除对象。
refreshTables代码中的just reloads the data是什么意思?在删除行之前尝试做同样的事情。
或者添加需要的20行来让代理工作。

+0

我使用NSFetchedResultsController和一个核心数据源没有问题。 sans-animation代码成功移除了coredata对象。这只是造成麻烦的动画。 – glenstorey 2010-10-30 10:54:46

+0

@glenstorey我想我第一次没有彻底地读过你的问题,看到我的编辑。 – 2010-10-30 11:34:24

17

当我们使用NSFetchedResultsController作为UITableView的DataSource时,我们不能在函数tableView: commitEditingStyle: forRowAtIndexPath:中调用deleteRowsAtIndexPaths: withRowAnimation: ,这会引发异常,如上面提到的问题。

解决此问题的一种方法是从协议NSFetchedResultsControllerDelegate调用[self.tableView reloadData]controllerDidChangeContent:。它实际上解决了,但是,不再有删除淡出动画。

因此,另一种方便的方法是在controller: didChangeObject: atIndexPath: forChangeType: newIndexPath:中调用[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]

示例代码如下:


- (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]; 
    } 
} 
+0

这对我来说是一个很好的答案,令人沮丧的“深夜”类问题! – seanicus 2012-09-27 03:29:09