使用 NSFetchedResultsController 删除部分中的最后一行 -> 崩溃

Posted

技术标签:

【中文标题】使用 NSFetchedResultsController 删除部分中的最后一行 -> 崩溃【英文标题】:Deleting last row in a section -> crash, using NSFetchedResultsController 【发布时间】:2012-03-06 21:43:45 【问题描述】:

我正在使用 NSFetchedResultsController。以前我遇到过类似的问题,当数据库没有表视图的条目但随后创建了一个时,我发现必须至少有一个部分,所以我修复了这个问题。但是现在当我有两个部分时它崩溃了,每个部分都有一行,我删除了一行,所以部分应该消失->崩溃。表示更新前的段数(2)不等于删除的段数(0)。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    // Return 1 if the fetchedResultsController section count is zero
    return [[fetchedResultsController sections] count] ? : 1;


- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section 
    // check if we really have any sections in the managed object:
    if (!fetchedResultsController.sections.count) return @"Persoonlijk";

    id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo name];


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    // check if we really have any sections in the managed object:
    if (!fetchedResultsController.sections.count) return 0;

    id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
    return [sectionInfo numberOfObjects];

更新 删除行的方法:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath 
    if (editingStyle == UITableViewCellEditingStyleDelete) 
        // Delete schedule
        NSManagedObjectContext *context = [fetchedResultsController managedObjectContext];
        [context deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]];

        // Save the context.
        NSError *error = nil;
        if (![context save:&error]) 
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            exit(-1);
        
    

【问题讨论】:

这一行是怎么回事:return [[fetchedResultsController section] count] ? : 1;您缺少中间参数。我认为您实际上缺少第一个参数并且将它们放在错误的位置。 看起来很奇怪,但实际上是正确的 :) 这是 return [[fetchedResultsController section] count] > 0 的简写版本? [[fetchedResultsController section] count] : 1; 我发现该消息通常意味着您实际获取消息以执行删除/删除的方法出现问题。从您的帖子看来,您实际上并没有更改它的部分数量?也许也发布您用于删除部分的代码? 好的,我用你要求的方法更新了我的帖子。 这对我来说看起来是正确的,两个后续问题 1)您确定调用代码时 fetchedResultsController 存在吗?我知道这听起来有点愚蠢,但我会检查一下。然后 2)如果您人为地更改表的节数,而不是仅使用“[[fetchedResultsController section] count]”作为节数的返回值,您确定有一个对象被传递给“删除对象:“? 【参考方案1】:

我找到了问题/解决方案:

我没有这种情况所需的 didChangeSection 委托方法!

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

【讨论】:

【参考方案2】:

我遇到了同样的问题。但是,仅实现 controller:didChangeSection:atIndex:forChangeType 方法并不能解决我的崩溃问题。我必须做的是在一次原子更新中进行多个表视图更新(部分删除 + 将行从刚刚删除的部分移动到现有的或新的部分)。我只是补充说:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller

    [self.tableView beginUpdates];


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller

    [self.tableView endUpdates];

【讨论】:

以上是关于使用 NSFetchedResultsController 删除部分中的最后一行 -> 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

核心数据保存竞争条件错误

在 Swift 3 中难以配置 NSFetchedResultsController

为啥 beginUpdates/endUpdates 会重置表视图位置以及如何阻止它这样做?

测试使用

第一篇 用于测试使用

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?