2014-01-19 46 views
2

從NSFetchedResultsController提供的UITableView刪除行會導致我的應用程序崩潰。NSFetchedResultsController:刪除1行導致應用程序崩潰

錯誤是:

* Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit/UIKit-2903.23/UITableView.m:1330
*
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 (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'

我只想刷到刪除。我刪除代碼是這樣的:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {  
    id sectionObjects = [[self.fetchedResultsController sections] objectAtIndex:section]; 
    NSInteger nbObjects = [sectionObjects numberOfObjects]; 
    return nbObjects; 
} 

它看起來像:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    [self.tableView beginUpdates]; 
    SequenceData *sd = [self.fetchedResultsController objectAtIndexPath:indexPath]; 
    [self.managedObjectContext deleteObject:sd]; 
    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
          withRowAnimation:UITableViewRowAnimationFade]; 
    [self.tableView endUpdates]; 
} 

我NSFetchedResultsController設置就像雷Wanderlich的教程(http://www.raywenderlich.com/999/core-data-tutorial-for-ios-how-to-use-nsfetchedresultscontroller

行數由以下因素決定提取未更新(行數不變)。我是否需要取回自己(這不是由取數控制器負責)?

顯然有一些基本的我在這裏失蹤。不要猶豫,提出基本的答案。

我首先用controller:didChangeObject:...方法實現了這個。錯誤是一樣的,但有些細節不同。

編輯 我相信我的問題已修復。兩個答案(來自CX和Martin)都幫我找到了答案。馬丁得到了答案,因爲這讓我有點明白了更好的解釋...

回答

12

不要叫

[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 

如果使用已取得的成果控制器。只有

[self.managedObjectContext deleteObject:sd]; 

獲取的成果控制器委託方法didChangeObject:然後自動調用, 刪除對象,並調用deleteRowsAtIndexPaths:

所以在你的情況下,該行被刪除了兩次,並導致了異常。

請注意,這裏不需要beginUpdates/endUpdates

+0

謝謝。實現您的答案不會使應用程序崩潰,但該行不會從表視圖中刪除。但是,數據被刪除。我需要任何類型的didChangeObject實現嗎? – invalidArgument

+0

@invalidArgument:是的,您必須實現4個獲取結果控制器委託方法。看看*「還有一件事 - 我們需要實現NSFetchedResultsController的委託方法」*和本教程中的以下代碼。 - 它也記錄在https://developer.apple.com/library/ios/documentation/CoreData/Reference/NSFetchedResultsControllerDelegate_Protocol/Reference/Reference.html中。 –

+0

實現這些方法會讓我的應用再次崩潰。所以在'commitEditingStyle'中,我只是刪除了這個對象。在'didChangeObject'中,它是從教程中複製粘貼的(因此在那裏有'deleteRowsAtIndexPaths')。異常實際上是在該行上引發的,indexPath和newIndexPath都是零。 (我還添加了'controllerWillChanteContent'和'controllerDidChangeContent') – invalidArgument

4

如果你想刪除一行,你只需要刪除managedObject。

if (editingStyle == UITableViewCellEditingStyleDelete) 
{ 
    [self.managedObjectContext deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]]; 

    NSError *error = nil; 
    if (![self.managedObjectContext save:&error]) { 
     // handle error 
    } 
} 

刪除管理對象觸發NSFetchResultController委託方法,他們將更新tableView

編輯

你應該實現NSFetchResultController委託方法

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{ 
switch(type) { 
case NSFetchedResultsChangeDelete: 
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
} 


//// 
    default: 
    break; 
    } 

因爲當你與像NSFetchedResultsController數據源的工作,所有的改變必須來自那裏,你的表只反映了他們。

+0

謝謝。我對你的建議的回答將與我給馬丁的回覆相似。數據被刪除,但行不會消失。我應該尋找什麼? – invalidArgument

+0

你在實現NSFetchResultController的代表...? –

+0

是的,我是。 'controllerWillChangeContent','controller:didChangeObject:...'和'controllerDidChangeContent' – invalidArgument