web-dev-qa-db-fra.com

TableView reloadData vs beginUpdates & endUpdates

J'ai eu un problème délicat concernant la mise à jour de ma TableView, j'obtiens des résultats différents en utilisant différentes méthodes de mise à jour, laissez-moi vous expliquer:

Situation 1: J'utilise [tbl reloadData];tbl est ma TableView, pour mettre à jour la TableView - fonctionne comme prévu.

Situation 2: J'utilise:

[tbl beginUpdates];
[tbl reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationRight];
[tbl endUpdates];

tbl est mon TableView et indexPaths est un tableau contenant tous les chemins d'accès index présents dans le TableView. Maintenant, le tableau est très bien, il contient tous les indexPaths corrects (double et triple vérifié) mais pour une raison quelconque - cela ne fonctionne pas comme prévu.

Maintenant, je me rends compte que c'est un problème XY (où je demande Y mais mon problème est vraiment X parce que je pense que résoudre Y résoudra X) et c'est seulement parce que je pense que c'est un peu compliqué d'expliquer X (la conséquence dudit problème ci-dessus) d'une manière simple, donc je préfère m'abstenir si possible.

Donc, à ma question: Y a-t-il une différence entre les deux façons de mettre à jour le TableView (à part le bit d'animation bien sûr) ou dois-je soupçonner que le problème réside ailleurs?

EDIT: D'accord, je vais essayer d'expliquer quels sont les symptômes:

Dans la méthode cellForRowAtIndexPath- j'ajoute un bouton à chaque cellule avec une balise affectée qui est égale à la ligne indexPath de la cellule, comme ceci:

btn.tag = indexPath.row;

La raison pour laquelle je fais cela est que je puisse identifier chaque bouton car ils appellent tous la même fonction:

- (void)btnPressed:(id)sender

Lorsque je mets ensuite à jour les cellules - parce que certaines valeurs dans les cellules ont changé - la situation 1 fait tout fonctionner correctement, la situation 2 cependant - mélange les balises de sorte que la prochaine fois que l'un des boutons est enfoncé, elles n'ont plus les balises correctes.

La confusion me semble aléatoire, mais la randomisation se produit différemment selon le bouton de cellule sur lequel j'appuie en premier. J'espère que cela clarifie mon problème.

30
Tobias Tovedal

Depuis la documentation UITableView

beginUpdates
Commencez une série d'appels de méthode qui insèrent, suppriment ou sélectionnent des lignes et des sections du récepteur.

Cela signifie que vous ne devez pas l'utiliser sauf si vous insérez, supprimez ou sélectionnez. Vous ne faites rien de tout cela.

De plus, vous devez terminer beginUpdates par endUpdates, pas reloadData. Documentation:

Ce groupe de méthodes doit se terminer par une invocation de endUpdates.

22
Mundi

La première différence entre reloadData et reloadRowsAtIndexPaths est qu'il y a 2 UITableViewCell objets alloués simultanément pour le même indexPath lors de l'exécution de reloadRowsAtIndexPaths (car la vue de table "se mélange") dans la nouvelle cellule). Cela n'est parfois pas prévu par le code dans cellForRowAtIndexPath. La surprise vient du fait que même si une cellule a déjà été allouée pour un identifiant de cellule particulier, la vue de table ne vous rend pas cette cellule dans dequeueReusableCellWithIdentifier lors de l'appel de reloadRowsAtIndexPaths, il renvoie à la place nil. En contradiction, reloadData réutilise les cellules qu'il a déjà allouées.

La deuxième différence est que endUpdates après que reloadRowsAtIndexPaths appelle directement cellForRowAtIndexPath (si vous y définissez un point d'arrêt, endUpdates est visible dans la trace de la pile) tandis que reloadData planifie les appels vers cellForRowAtIndexPath à une date ultérieure (non visible dans la trace de la pile).

Cependant, vous devrez publier un peu plus de code pour nous donner un aperçu de ce que vous faites là-bas. En principe, les indexPaths des nouvelles cellules sont identiques aux anciennes également avec reloadRowsAtIndexPaths tant que vous ne supprimez pas ou n'insérez pas de lignes.

5
Leo

Appelez cette méthode si vous souhaitez que les opérations d'insertion, de suppression et de sélection suivantes (par exemple, cellForRowAtIndexPath: et indexPathsForVisibleRows) soient animées simultanément.

Je pense que c'est ce que tu veux. beginUpdates & endUpdates peuvent changer la vue UItableview avec animation.

1
gfxcc