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

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

[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? 该文件说,使用beginUpdatesendUpdates做两件事情:

  1. 同时animation一组插入,删除和其他操作
  2. “如果你不在这个块内部进行插入,删除和select调用,那么行数等表格属性可能会失效。” (这到底是什么意思呢?)

但是,如果我不使用beginUpdates / endUpdates,表视图看起来像它animation的各种变化同时,我不认为表视图的内部一致性被破坏。 那么用beginUpdates / endUpdates做复杂的方法有什么好处呢?

每次添加/删除表项时,都会调用tableView:numberOfRowsInSection:方法 – 除非用begin / endUpdate包围这些调用。 如果你的数组和表视图项不同步,没有开始/结束调用将抛出exception。