2011-01-09 184 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

我已经测试了从现有部分与其中另一个条目到不存在部分以及从仅有一行到另一个不存在部分的部分。

相关问题