2010-10-30 38 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