NSFetchedResultsController在objectAtIndexPath上崩溃了?

时间:2013-11-10 23:04:46

标签: objective-c core-data nsfetchedresultscontroller

尝试访问NSFetchedResultsController中的对象时,我遇到了崩溃。

2013-11-10 15:15:06.568 Social[11503:70b] CoreData: error: Serious application error.  Exception was caught during Core Data change processing.  This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification.  *** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds for empty array with userInfo (null)
2013-11-10 15:15:06.570 Social[11503:70b] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds for empty array'

viewDidLoad中

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.resultController = [DataEngine sharedInstance].postsFetchedResultController;
    self.resultController.delegate = self;
    [self.resultController performFetch:nil];

    [self.tableView reloadData];

    [[DataEngine sharedInstance] fetchInBackground];
}

结果控制器代表

#pragma mark - NSFetchedResultsControllerDelegate Methods -

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

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView endUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
    switch (type)
    {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertRowsAtIndexPaths:@[indexPath]
                                  withRowAnimation:UITableViewRowAnimationAutomatic];
            break;

        case NSFetchedResultsChangeUpdate:
            [self.tableView reloadRowsAtIndexPaths:@[indexPath]
                                  withRowAnimation:UITableViewRowAnimationAutomatic];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteRowsAtIndexPaths:@[indexPath]
                                  withRowAnimation:UITableViewRowAnimationAutomatic];
            break;

        case NSFetchedResultsChangeMove:
            [self.tableView moveRowAtIndexPath:indexPath toIndexPath:newIndexPath];
            break;

        default:
            break;
    }
}

表格视图

#pragma mark - UITableView Delegate & Datasrouce -

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.resultController.fetchedObjects.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return [self cellForRowAtIndexPath:indexPath];
}

2 个答案:

答案 0 :(得分:0)

下面一行崩溃的一个原因可能是您在使用它重新调整表格部分的行数后更新了self.resultContrlller。确保如果您不断更新self.resultContrlller对象,那么您将获取它的副本然后用于您的表格绘图。

// This code does not prevent crash. Changing your regular code to modern objective-C way
Post *post = [self.resultContrlller fetchedObjects][indexPath.row];

当表重新加载时,数据源不应更改。您应该使用fetchedObjects的副本来加载表。因此,在重新加载表之前,请先复制[[self.resultContrlller fetchedObjects] copy]并将其用于表格绘制。您的主要来源可以继续改变。在使用副本完成表重新加载后,如果数据发生更改,您可能需要重新加载它。当您的数据源变化快于表重新加载时,会发生此类崩溃。

答案 1 :(得分:0)

在我的一个NSManagedObject子类中,我遇到了导致问题的代码。 NSSets在NSManagedObejcts上自动初始化,无需初始化它们。

- (void)awakeFromFetch
{
    if (!self.comments)
        self.comments = [NSMutableSet set];

    if (!self.medias)
        self.medias = [NSMutableSet set];
}

另一个问题是在插入indexPath期间为null时,我不得不使用newIndexPath

case NSFetchedResultsChangeInsert:
    [self.tableView insertRowsAtIndexPaths:@[newIndexPath]
                          withRowAnimation:UITableViewRowAnimationAutomatic];
    break;