2011-01-09 124 views
5

我有一個標準的拆分視圖控制器,具有詳細視圖和表視圖。按詳細視圖中的按鈕可以使對象在表視圖的排序中更改其位置。這工作正常,只要結果訂購更改不會導致添加或刪除部分。即一個對象可以改變它在一個部分的順序或者從一個部分切換到另一個部分。這些訂購更改正常工作沒有問題。但是,如果對象試圖移動到尚不存在的部分,或者是最後一個要離開某個部分的對象(因此需要移除該部分),那麼應用程序會崩潰。「didChangeSection:」NSfetchedResultsController委託方法不被調用

NSFetchedResultsControllerDelegate有方法來處理在這些情況下應該調用的被添加和刪除的部分。但是這些委託方法由於某種原因沒有被調用。

有問題的代碼是樣板:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { 
NSLog(@"willChangeContent"); 
    [self.tableView beginUpdates]; 
} 

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo 
      atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { 
NSLog(@"didChangeSection"); 

    switch(type) { 
     case NSFetchedResultsChangeInsert: 
      [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeDelete: 
      [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
    } 
} 

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject 
     atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type 
     newIndexPath:(NSIndexPath *)newIndexPath {  
NSLog(@"didChangeObject"); 

    UITableView *tableView = self.tableView; 

    switch(type) { 

     case NSFetchedResultsChangeInsert: 
      [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeDelete: 
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      break; 

     case NSFetchedResultsChangeUpdate: 
      [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; 
      break; 

     case NSFetchedResultsChangeMove: 
      [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; 
      [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade]; 
      break; 
    } 
} 

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { 
NSLog(@"didChangeContent"); 
    [self.tableView endUpdates]; 

    [detailViewController.reminderView update]; 
} 

啓動應用程序,然後導致的最後一個對象留在下面的輸出部分結果:

2011-01-08 23:40:18.910 Reminders[54647:207] willChangeContent 
2011-01-08 23:40:18.912 Reminders[54647:207] didChangeObject 
2011-01-08 23:40:18.914 Reminders[54647:207] didChangeContent 
2011-01-08 23:40:18.915 Reminders[54647:207] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1145.66/UITableView.m:825 
2011-01-08 23:40:18.917 Reminders[54647:207] Serious application error. Exception was caught during Core Data change processing: Invalid update: invalid number of sections. The number of sections contained in the table view after the update (5) must be equal to the number of sections contained in the table view before the update (6), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted). with userInfo (null) 

正如你所看到的,「willChangeContent」,「didChangeObject」(移動有問題的對象)和「didChangeContent」都被正確調用。基於蘋果的NSFetchedResultsControllerDelegate文檔「didChangeSection」應該在「didChangeObject」之前被調用,這將防止導致崩潰的異常。

所以我想問題是我如何確保didChangeSection被調用?

在此先感謝您的幫助!

回答

1

此問題是由於使用transient屬性作爲sectionNameKeyPath引起的。當我將用於sectionNameKeyPath的屬性存儲在數據庫中時,問題就消失了。使用transient屬性作爲sectionNameKeyPath時,我不知道是否有辦法使基於NSFetchedResultsController內容更新的部分發生更改。現在我正在考慮這個瞬態屬性的限制。

+0

我在我的項目中遇到了非常類似的問題。 didChangeSection似乎並不會在應該調用時調用。我爲sectionNameKeyPath使用「objectID.URIRepresentation」,因爲我希望每個對象都在它自己的部分中。我正在iPhone 5.1模擬器中測試。我的FRC根據值排序(增加到減少),所以如果一個對象的值改變,我的部分的順序也應該改變,但didChangeSection函數永遠不會被調用。你有什麼直覺爲什麼這可能會發生?謝謝。 – klyngbaek 2012-03-25 00:04:26

+0

我也在爲此苦苦掙扎,首先爲sectionNameKeyPath指定nil。當所有的對象被刪除時,我返回0的tableView的數據源方法(fetchedObjects == 0),這打破了tableView的部分數。如果您需要觸發此委託方法,則應該指定某種類型的sectionNameKeyPath。現在看起來很明顯,只是認爲我會分享那些像我一樣木頭的人。 – Schoob 2012-09-04 11:05:37

1

我在我的應用程序(sectionNameKeyPath中的瞬態屬性)中做同樣的事情,並沒有看到你遇到的問題。我在iOS 4.2.1上測試了這個...有一個已知的錯誤,你不能相信任何在iOS 3.X中的FRC委託回調,你必須在controllerDidChangeContent:消息中完成一個完整的[tableView reloadData]。 see the FRC documentation

我已經測試了從現有部分與其中另一個條目到不存在部分以及從僅有一行到另一個不存在部分的部分。