web-dev-qa-db-fra.com

Comment résoudre ce crash de CollectionView?

Mon application a deux CollectionViewControllers. Un seul est visible à un moment donné.

J'ai créé la structure suivante sur le storyboard: deux vues de conteneur superposées. Chaque vue de conteneur a une CollectionViewController incorporée. La visibilité d'une vue de conteneur particulière détermine quelle collectionViewController est visible.

C'est le problème. CollectionViewControllers reçoivent tous deux des données en parallèle, mais iOS a un bogue qui provoque le blocage de l'application si un CollectionViewController tente d'exécuter une insertion à l'aide de performBatchUpdates alors qu'elle est invisible.

En essayant d’empêcher cela, j’ai créé un drapeau BOOL sur les deux CollectionViewControllers afin qu’ils puissent savoir s’ils sont visibles et exécuter ou non la performBatchUpdates. Quelque chose comme:

if (self.isThisCollectionViewVisible == NO) return;

[self.collectionView performBatchUpdates:^{
   // bla bla... perform insert,m remove...

Cela résout une partie du problème. Mais l'application continue de planter à la condition suivante: si j'appuie sur le bouton pour passer à la variable invisible CollectionViewController, la rendant visible pendant la réception des mises à jour.

Je veux dire ceci: appelons A la première CollectionViewController et B la seconde. A est visible et B est invisible à ce stade. B commence à recevoir des données et tente de créer une performBatchUpdates, mais comme elle est invisible, la fonction if (self.isThisCollectionViewVisible == NO) return; empêche performBatchUpdates de s'exécuter, ce qui est correct. Maintenant, je rends A invisible et B visible. À ce stade, l'indicateur self.isThisCollectionViewVisible est défini sur YES et performBatchUpdates provoque le blocage de l'application avec cette erreur:

* Échec de l'assertion dans - [CollectionView _endItemAnimationsWithInvalidationContext: tentivelyForReordering:], /BuildRoot/Library/Caches/com.Apple.xbs/Sources/UIKit/UIKit-3512.60.7/UICollectionView.m:4625 * Terminer le script de sauvegarde exception non interceptée 'NSInternalInconsistencyException', motif: 'Mise à jour non valide: nombre d'éléments non valide dans la section 0. Le nombre d'éléments contenus dans une section existante après la mise à jour (76) doit être égal au nombre d'éléments contenus dans cette section avant la mise à jour. (70), plus ou moins le nombre d'éléments insérés ou supprimés de cette section (5 insérés, 2 supprimés) et plus ou moins le nombre d'éléments entrés ou sortis de cette section (0 déplacé, 0 déplacé). '

Je pense que la CollectionViewController n'est vraiment pas encore prête et mise à jour pour pouvoir faire une performBatchUpdates... et il ne s'agit pas de ne pas mettre à jour la source de données précédemment car elle est en cours de mise à jour.

Quelles vérifications puis-je faire pour empêcher cela?

NOTE: J'ai remarqué quelque chose d'étrange à propos de cet accident en particulier. Il est indiqué que 5 éléments sont insérés et 2 supprimés. En réalité, 3 éléments sont insérés, 0 supprimés et 2 modifiés lorsque les blocages se produisent.

11
SpaceDog

Pour moi, ajouter self.collectionView.numberOfItemsInSection(0) a corrigé le crash. La collectionView a des problèmes lors de l'insertion d'éléments quand elle n'est pas visible.

On dirait que je ne suis pas seul avec ma solution: http://www.openradar.me/15262692

16
João Nunes

Cet incident vous a indiqué que vous n'aviez pas mis à jour votre source de données pour la collecte. Vous devez mettre à jour votre source de données (tableau ou dictionnaire) et recharger les données de vue de la collection après avoir effectué performBatchUpdates

Mise à jour non valide: nombre d'éléments non valide dans la section 0. Le nombre d'éléments contenus dans une section existante après la mise à jour (76) doit être égal au nombre d'éléments contenus dans cette section avant la mise à jour (70), plus ou moins le nombre d’éléments insérés ou supprimés de cette section (5 insérés, 2 supprimés) et plus ou moins le nombre d’éléments entrés ou sortis de cette section (0 déplacé, 0 déplacé). '

Comme écrit dans les documents Apple

Les suppressions sont traitées avant les insertions dans les opérations par lots. Cela signifie que Les index des suppressions sont traités par rapport aux index de L'état de la vue de collection avant l'opération de traitement par lots et que les index Des insertions sont traités par rapport aux index. de l'état après toutes les suppressions dans l'opération par lots.

Alors, déplacez les modifications avant les insertions et le tour sera joué!

3
Karaban

J'ai rencontré la même erreur aujourd'hui, pour moi, dans le bloc performBatchUpdates, remplace ceci:

  NSArray *selectedItemsIndexPaths = [self.collectionView indexPathsForSelectedItems];

avec ça:

  NSIndexPath *selectedIndexPath = [NSIndexPath indexPathForRow:self.selectIndex inSection:0];
  NSArray *selectedItemsIndexPaths = @[selectedIndexPath];

Maintenir l'index par moi-même, c'est bon maintenant. L'erreur ne doit pas être associée à la source de données, si vous avez déjà mis à jour la source de données. Cela peut être lié à la réutilisation des cellules.

0
Hongli Yu