“didChangeSection:” NSfetchedResultsController委托方法未被调用 [英] "didChangeSection:" NSfetchedResultsController delegate method not being called

查看:144
本文介绍了“didChangeSection:” NSfetchedResultsController委托方法未被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个标准的分割视图控制器,有一个详细视图和一个表视图。按下详细视图中的按钮可以使对象在表视图的顺序中更改其位置。这工作正常,只要结果排序更改不导致添加或删除节。也就是说一个对象可以改变它在一个部分中的顺序或从一个部分切换到另一个部分。这些顺序更改工作正常没有问题。但是,如果对象试图移动到一个尚不存在的部分,或者是最后一个离开部分的对象(因此需要删除它的部分),那么应用程序会崩溃。



NSFetchedResultsControllerDelegate具有处理添加和删除部分的方法,应在这些情况下调用。



有问题的代码是样板:

   - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
NSLog(@willChangeContent);
[self.tableView beginUpdates]; (NSFetchedResultsChangeType)type(NSFetchedResultsChangeType)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type(NSFetchedResultsSectionInfo) {
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提醒[54647:207] willChangeContent 
2011 -01-08 23:40:18.912提醒[54647:207] didChangeObject
2011-01-08 23:40:18.914提醒[54647:207] didChangeContent
2011-01-08 23:40: 18.915提醒[54647:207] *** - - [UITableView _endCellAnimationsWithContext:]中的声明失败,/SourceCache/UIKit_Sim/UIKit-1145.66/UITableView.m:825
2011-01-08 23:40:18.917提醒[ 54647:207]严重的应用程序错误。在核心数据更改处理期间捕获到异常:更新无效:部分数量无效。更新(5)之后,表视图中包含的节数必须等于更新前的表视图(6)中包含的节数,加上或减去插入或删除的节数(插入0个,0删除)。与用户信息(null)



如你所见,willChangeContent,didChangeObject有问题),和didChangeContent都被正确调用。基于Apple的NSFetchedResultsControllerDelegate文档didChangeSection应该在didChangeObject之前调用,这将阻止导致崩溃的异常。



所以我想问题是如何

解决方案



div>

此问题是由使用transient属性作为sectionNameKeyPath造成的。当我改为存储用于sectionNameKeyPath的属性在数据库中,问题消失了。我不知道是否有一种方法来获取基于NSFetchedResultsController内容更改时使用临时属性作为sectionNameKeyPath更新的部分。现在我考虑这是暂时属性的限制。


I have a standard split view controller, with a detail view and a table view. Pressing a button in the detail view can cause the an object to change its placement in the table view's ordering. This works fine, as long as the resulting ordering change doesn't result in a section being added or removed. I.e. an object can change it's ordering in a section or switch from one section to another. Those ordering changes work correctly without problems. But, if the object tries to move to a section that doesn't exist yet, or is the last object to leave a section (therefore requiring the section its leaving to be removed), then the application crashes.

NSFetchedResultsControllerDelegate has methods to handle sections being added and removed that should be called in those cases. But those delegate methods aren't being called for some reason.

The code in question, is boilerplate:

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

Starting the application, and then causing the last object to leave a section results in the following output:

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)

As you can see, "willChangeContent", "didChangeObject" (moving the object in question), and "didChangeContent" were all called properly. Based on the Apple's NSFetchedResultsControllerDelegate documentation "didChangeSection" should have been called before "didChangeObject", which would have prevented the exception causing the crash.

So I guess the question is how do I assure that didChangeSection gets called?

Thanks in advance for any help!

解决方案

This problem was caused by using a transient attribute as the sectionNameKeyPath. When I instead stored the attribute used for the sectionNameKeyPath in the database, the problem went away. I don't know if there is a way to get the sections updated based on a NSFetchedResultsController content changes when using a transient attribute as a sectionNameKeyPath. For now I am considering this a limitation of transient attributes.

这篇关于“didChangeSection:” NSfetchedResultsController委托方法未被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆