ios - ¿Cuál es el beneficio de llamar a beginUpdates/endUpdates para una UITableView en lugar de no hacerlo?
objective-c (1)
Cada vez que agrega o elimina un elemento de la tableView:numberOfRowsInSection:
, se llama al método tableView:numberOfRowsInSection:
menos que rodee estas llamadas con begin
/ endUpdate
. Si su matriz y los elementos de la vista de tabla no están sincronizados, sin las llamadas de inicio / finalización se lanzará una excepción.
Tengo una matriz de matrices que estoy usando para el origen de datos de una vista de tabla. En una ocasión, es posible que tenga que hacer algunas modificaciones complicadas a esta estructura de datos. (Por ejemplo, es posible que deba hacer una secuencia de operaciones: eliminar una fila aquí, insertar una fila allí, insertar una sección aquí, eliminar otra fila, insertar otra fila, eliminar otra fila, insertar otra sección. idea.) Esto es fácil de hacer si, para cada operación en la secuencia, solo actualizo la fuente de datos y luego hago la actualización correspondiente para la vista de tabla inmediatamente. En otras palabras, el pseudocódigo se verá así:
[arrayOfArrays updateForOperation1];
[tableView updateForOperation1];
[arrayOfArrays updateForOperation2];
[tableView updateForOperation2];
[arrayOfArrays updateForOperation3];
[tableView updateForOperation3];
[arrayOfArrays updateForOperation4];
[tableView updateForOperation4];
// Etc.
Sin embargo, si tuviera que rodear estas operaciones en un "bloque" de BeginUpdates / endUpdates, este código ya no funciona. Para ver por qué, las imágenes comienzan con una vista de tabla vacía e insertan cuatro filas por turno al comienzo de la primera sección. Aquí está el pseudocódigo:
[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];
Cuando se llama a endUpdates, ¡la vista de tabla descubre que está insertando cuatro filas todas colisionando en la fila 0!
Si REALMENTE queremos mantener parte del código beginUpdates / endUpdates, tenemos que hacer algo complicado. (1) Realizamos todas las actualizaciones al origen de datos sin actualizar la vista de tabla a medida que avanzamos. (2) Descubrimos cómo las partes de la fuente de datos antes de todas las actualizaciones se asignan a las partes de la fuente de datos después de todas las actualizaciones para averiguar qué actualizaciones necesitamos realizar para la vista de tabla. (3) Finalmente, actualice la vista de tabla. El pseudocódigo se ve algo así para lograr lo que intentábamos hacer en el ejemplo anterior:
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];
¿Por qué hacer todo esto por el bien de beginUpdates / endUpdates? La documentación dice que debes usar beginUpdates y endUpdates para hacer dos cosas:
- Animar un montón de insertar, eliminar y otras operaciones simultáneamente
- "Si no realiza las llamadas de inserción, eliminación y selección dentro de este bloque, los atributos de la tabla, como el recuento de filas, podrían no ser válidos". (¿Qué significa esto exactamente de todos modos?)
Sin embargo, si no uso beginUpdates / endUpdates, la vista de tabla parece que está animando los distintos cambios simultáneamente, y no creo que la consistencia interna de la vista de tabla esté dañada. Entonces, ¿cuál es el beneficio de hacer el enfoque complicado con beginUpdates / endUpdates?