NSFetchedResultsController:更新期间使用NSManagedObjectContext导致崩溃 [英] NSFetchedResultsController: using of NSManagedObjectContext during update brings to crash

查看:47
本文介绍了NSFetchedResultsController:更新期间使用NSManagedObjectContext导致崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的控制器类的接口:

Here is the interface of my controller class:

@interface ProjectListViewController : UITableViewController <NSFetchedResultsControllerDelegate> {
    NSFetchedResultsController *fetchedResultsController;
    NSManagedObjectContext *managedObjectContext;
}

@end

我使用以下代码初始化 fetchedResultsController :

I use following code to init fetchedResultsController:

if (fetchedResultsController != nil) {
    return fetchedResultsController;
}

    // Create and configure a fetch request with the Project entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Project" inManagedObjectContext:managedObjectContext];
    [fetchRequest setEntity:entity];

    // Create the sort descriptors array.
    NSSortDescriptor *projectIdDescriptor = [[NSSortDescriptor alloc] initWithKey:@"projectId" ascending:YES];
    NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:projectIdDescriptor, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];

    // Create and initialize the fetch results controller.
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest 
                                                                                            managedObjectContext:managedObjectContext 
                                                                                              sectionNameKeyPath:nil 
                                                                                                       cacheName:nil];
    self.fetchedResultsController = aFetchedResultsController;
    fetchedResultsController.delegate = self;

如您所见,我正在使用与控制器类中定义的相同的 managedObjectContext

As you can see, I am using the same managedObjectContext as defined in my controller class

这里采用了NSFetchedResultsControllerDelegate协议:

Here is an adoption of the NSFetchedResultsControllerDelegate protocol:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    // The fetch controller is about to start sending change notifications, so prepare the table view for updates.
        [self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
        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:(TDBadgedCell *)[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
                break;

            case NSFetchedResultsChangeMove:
                if (newIndexPath != nil) {
                    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                    [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                }
                else {
                    [tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
                }
            break;
        }
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
        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)controllerDidChangeContent:(NSFetchedResultsController *)controller {
        [self.tableView endUpdates];
}

在_configureCell:atIndexPath:方法内部,我有以下代码:

Inside of the _configureCell:atIndexPath: method I have following code:

    NSFetchRequest *issuesNumberRequest = [NSFetchRequest new];
    NSEntityDescription *issueEntity = [NSEntityDescription entityForName:@"Issue" inManagedObjectContext:managedObjectContext];
    [issuesNumberRequest setEntity:issueEntity];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"projectId == %@", project.projectId];
    [issuesNumberRequest setPredicate:predicate];
    NSUInteger issuesNumber = [managedObjectContext countForFetchRequest:issuesNumberRequest error:nil];
    [issuesNumberRequest release];

我再次使用managedObjectContext.

I am using the managedObjectContext again.

但是当我尝试插入新的Project时,应用程序崩溃,但出现以下异常:

But when I am trying to insert new Project, app crashes with following exception:

-[UITableView中的断言失败 _endCellAnimationsWithContext:],/SourceCache/UIKit_Sim/UIKit-984.38/UITableView.m:774 由于未捕获而终止应用程序 例外 'NSInternalInconsistencyException', 原因:无效的更新:无效 第0节中的行数. 包含的行数 更新后的现有部分(4) 必须等于行数 包含在该部分之前 更新(4),加上或减去数字 从中插入或删除的行数 部分(已插入1个,已删除0个).'

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

幸运的是,我找到了一种解决方法:如果我在_configureCell:atIndexPath:方法应用程序内创建并使用单独的NSManagedObjectContext不会崩溃!

Fortunately, I've found a workaround: if I create and use separate NSManagedObjectContext inside of the _configureCell:atIndexPath: method app won't crash!

我只想知道,这种行为是否正确?

I only want to know, is this behavior correct or not?

这是一个示例项目. 请注意CrashMeViewController的'_configureCell:atIndexPath:'和'_addSomeRows'方法

Here is a sample project. Pay your attention to '_configureCell:atIndexPath:' and '_addSomeRows' methods of CrashMeViewController

推荐答案

在iOS 4.0中已修复

Fixed in iOS 4.0

这篇关于NSFetchedResultsController:更新期间使用NSManagedObjectContext导致崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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