更新UITableView将导致异常

时间:2010-08-13 01:23:35

标签: iphone exception

我有UITableViewController子类并实现了以下

  1. NSFetchedResultsController及其代表
  2. tableView:sectionForSectionIndexTitle:atIndex:
  3. tableView:titleForHeaderInSection:
  4. controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:

    case NSFetchedResultsChangeMove:
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
               withRowAnimation:UITableViewRowAnimationFade];
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
               withRowAnimation:UITableViewRowAnimationFade];
        break;
    

    在给定实体的数据模型中,我有临时属性uppercaseFirstLetterOfName,它将返回持久属性的第一个字母。

    这就是实现表项和侧索引的按字母顺序排列的部分。

    现在,如果我有一个部分的单个记录,那么我重命名它以便它将更改部分,我得到以下异常,这发生在NSFetchedResultsChangeMove之后的某个地方。

      

    ***断言失败 - [UITableView _endCellAnimationsWithContext:],/ SourceCache / UIKit_Sim / UIKit-984.38 / UITableView.m:774

         

    Core Data期间发现了异常   更改处理:无效更新:   第0节中的行数无效。   包含的行数   更新后的现有部分(1)   必须等于行数   包含在该部分之前   更新(1),加号或减号   从中插入或删除的行数   部分(0已插入,1已删除)。

    有什么想法吗?

    UPD更多代码:

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
    {
        NSInteger count = [[fetchedResultsController sections] count];
        return count;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView
                             numberOfRowsInSection:(NSInteger)section 
    {
        NSInteger numberOfRows = 0;
        if ([[fetchedResultsController sections] count] > 0) 
        {
            id <NSFetchedResultsSectionInfo> sectionInfo =
                  [[fetchedResultsController sections] objectAtIndex:section];
            numberOfRows = [sectionInfo numberOfObjects];
        }
        return numberOfRows;
    }
    

    ...

        NSSortDescriptor* sortByWordDescriptor = [[NSSortDescriptor alloc] 
                            initWithKey:@"subject" ascending:YES];
        NSArray* sortArray = [[NSArray alloc]
                            initWithObjects:sortByWordDescriptor, nil];
        [fetchRequest setSortDescriptors:sortArray];
    
        NSFetchedResultsController* controller = [[NSFetchedResultsController alloc]
                            initWithFetchRequest:fetchRequest 
                            managedObjectContext:managedObjectContext 
                            sectionNameKeyPath:@"uppercaseFirstLetterOfName" 
                            cacheName:@"Root"];
    

    UPD(修补): 目前我修改了这样的代码:

        case NSFetchedResultsChangeMove:
            NSUInteger tableSectionCount = [self.tableView numberOfSections];
            NSUInteger modelSectionCount = [[controller sections] count];
            if (modelSectionCount > tableSectionCount) 
            {
                [self.tableView insertSections:[NSIndexSet
                                    indexSetWithIndex:[newIndexPath section]]
                                    withRowAnimation:UITableViewRowAnimationNone];
            }
            else if(modelSectionCount < tableSectionCount)
            {
                if (tableSectionCount > 1) 
                {
                    [self.tableView deleteSections:[NSIndexSet
                                     indexSetWithIndex:[indexPath section]] 
                                     withRowAnimation:UITableViewRowAnimationNone];
                }
            }
            [tableView deleteRowsAtIndexPaths:[NSArray
                                     arrayWithObject:indexPath]
                                     withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray
                                     arrayWithObject:newIndexPath] 
                                     withRowAnimation:UITableViewRowAnimationFade];
    
            break;
    

    到目前为止还没有崩溃,但这是正确的解决方案吗?

3 个答案:

答案 0 :(得分:2)

我想我知道你发生了什么事。确保你有:

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

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

文档说明了“beginUpdates”方法:

  

如果要同时为后续插入,删除和选择操作(例如,cellForRowAtIndexPath:和indexPathsForVisibleRows)设置动画,请调用此方法。

这就是你正在做的事情:

[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];

干杯

答案 1 :(得分:0)

处理这些部分的代码会期望某个项目位于某个索引但该项目不再存在,并且当没有项目时返回nil时,您似乎没有为该场景编码。< / p>

答案 2 :(得分:0)

在执行tableView的任何insert或delete方法之前,你应该修改数据源数组。

    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
       withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
       withRowAnimation:UITableViewRowAnimationFade];

NSFetchedResultsChangeMove应该完成您的UI移动操作。 所以你需要做的是重新排序datasorce项目。