为UITableView调用beginUpdates / endUpdates有什么好处,而不是这样做?

时间:2014-04-24 05:07:57

标签: ios objective-c uitableview

我有一组数组,我用它来表视图的数据源。在一个时间实例中,我可能不得不对此数据结构进行一些复杂的修改。 (例如,我可能需要做的一系列操作是:在这里删除一行,在那里插入一行,在这里插入一个部分,删除另一行,插入另一行,删除另一行,插入另一部分 - 你得到了如果对于序列中的每个操作,我只更新数据源,然后立即对表视图执行相应的更新,这很容易做到。换句话说,伪代码看起来像:

[arrayOfArrays updateForOperation1];
[tableView updateForOperation1];

[arrayOfArrays updateForOperation2];
[tableView updateForOperation2];

[arrayOfArrays updateForOperation3];
[tableView updateForOperation3];

[arrayOfArrays updateForOperation4];
[tableView updateForOperation4];

// Etc.

但是,如果我将这些操作包含在beginUpdates / endUpdates"块中,"此代码不再有效。要了解原因,请先从空表视图开始,然后在第一部分的开头依次插入四行。这是伪代码:

[tableView beginUpdates];

[arrayOfArrays insertRowAtIndex:0];
[tableView insertRowAtIndexPath:[row 0, section 0]];

[arrayOfArrays insertRowAtIndex:0];
[tableView insertRowAtIndexPath:[row 0, section 0]];

[arrayOfArrays insertRowAtIndex:0];
[tableView insertRowAtIndexPath:[row 0, section 0]];

[arrayOfArrays insertRowAtIndex:0];
[tableView insertRowAtIndexPath:[row 0, section 0]];

[tableView endUpdates];

当调用endUpdates时,表视图发现你正在插入所有在第0行碰撞的四行!

如果我们真的想保留beginUpdates / endUpdates代码的一部分,我们必须做一些复杂的事情。 (1)我们在不更新表视图的情况下对数据源进行所有更新。 (2)我们弄清楚在所有更新之前数据源的各部分如何在所有更新之后映射到数据源的各个部分,以确定我们需要为表视图执行哪些更新。 (3)最后,更新表视图。伪代码看起来像这样,以完成我们在前面的例子中尝试做的事情:

oldArrayOfArrays = [self recordStateOfArrayOfArrays];

// Step 1:
[arrayOfArrays insertRowAtIndex:0];
[arrayOfArrays insertRowAtIndex:0];
[arrayOfArrays insertRowAtIndex:0];
[arrayOfArrays insertRowAtIndex:0];

// Step 2:
// Comparing the old and new version of arrayOfArrays,
// we find we need to insert these index paths:
// @[[row 0, section 0],
//   [row 1, section 0],
//   [row 2, section 0],
//   [row 3, section 0]];
indexPathsToInsert = [self compareOldAndNewArrayOfArraysToGetIndexPathsToInsert];

// Step 3:

[tableView beginUpdates];

for (indexPath in indexPathsToInsert) {
    [tableView insertIndexPath:indexPath];
}

[tableView endUpdates];

为什么这一切都是为了beginUpdates / endUpdates?文档说使用 beginUpdates endUpdates 做两件事:

  1. 动画一系列插入,删除和其他操作同时
  2. "如果您未在此块中进行插入,删除和选择调用,则行计数等表属性可能会变为无效。" (无论如何,这究竟意味着什么?)
  3. 但是,如果我不使用beginUpdates / endUpdates,表格视图看起来就像是同时动画了各种变化,我不认为表格视图的内部一致性正在腐败。那么使用beginUpdates / endUpdates进行复杂方法有什么好处?

1 个答案:

答案 0 :(得分:16)

每次添加/删除表格项时,都会调用tableView:numberOfRowsInSection:方法 - 除非您使用begin / endUpdate包围这些来电。如果您的数组和表视图项不同步,则在没有开始/结束调用的情况下将抛出异常。