UITableView - reloadData或reloadRowsAtIndexPaths:

时间:2017-09-01 18:52:00

标签: ios objective-c uitableview

这是我的情景:

我有一个带标签的单元格。当我第一次加载单元格时,模型可能没有标签所需的数据...所以当我发现(通过委托调用)模型刚刚获得标签数据或标签数据已更改时,我可以重新加载特定的单元格。我需要重新加载单元格的原因(而不仅仅是设置标签的文本)是它的高度可能会根据标签是否有文字而改变。

以下是我在委托电话中所做的事情:

- (void)modelLabelDataDidChangeForModel:(NSString *)modelId
{
    NSIndexPath *indexPath = [self indexPathForModel:modelId]; // Local method to get index path.
     MyCell *cell = (MyCell *) [self.table cellForRowAtIndexPath:indexPath];
    if (cell) {
        [self.table beginUpdates];
        [cell updateMostImportantContent];
        [self.table reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
        [self.table endUpdates];
    }
}

我在*** Assertion failure in -[UITableView _endCellAnimationsWithContext:]遇到了崩溃(endUpdates)因为它说更新后的行数与更新前的行数不匹配(因为我在更新块期间没有显式添加/删除任何行;我只是重新加载了1行。

所以这让我觉得模型可能同时进行了2次更改:标签数据正在改变1个项目(因此我的委托调用),但随后还有一个项目被添加到模型中(因此崩溃)。

所以这让我想一想,如何判断我是否需要拨打reloadData或者我是否可以使用reloadRowsAtIndexPaths:@[indexPath]重新加载1个单元格?

我是否必须自己跟踪模型,或者我可以使用表格视图来确定这一点并避免崩溃?

我的目标是提高效率:在需要时拨打reloadData,但在可以的时候拨打reloadRowsAtIndexPath:@[indexPath]

2 个答案:

答案 0 :(得分:0)

来自文档:

在beginUpdates和endUpdates方法定义的动画块中调用此方法时,其行为与deleteRowsAtIndexPaths:withRowAnimation:类似。 UITableView传递给方法的索引在任何更新之前在表视图的状态中指定。无论动画块中的插入,删除和重新加载方法调用的顺序如何,都会发生这种情况。

在我看来,您不需要或不需要这种电话或方法。您正在更新单个索引。 如果您确实想要更新多个索引,则应通过创建要更新的索引数组来进行不同的排列,然后在完成数据更新时使用beginUpdates / endUpdates系列。< / p>

答案 1 :(得分:0)

-endUpdates方法强制UITableView重新计算所有可见单元格的高度。在此之前,它会验证当前显示的数据和调用的一致性

 - numberOfSectionsInTableView:
 - tableView:numberOfRowsInSection:

dataSource的方法。 当您不致电-reloadData时,UITableView依赖于之前收集的数据(例如,部分数量,部分中的行数)是相同的。

当它不相同时,你会得到断言和崩溃。

为了使您的数据与UITableView的状态保持一致,您必须在beginUpdates / {{1}内删除/插入对象消失或新出现的索引路径上的单元格阻止。