web-dev-qa-db-fra.com

Erreur d'assertion UICollectionView sur des données obsolètes

En essayant de décharger un lot d'images de la vue de collection et de les remplacer par un autre lot, je rencontre une erreur dans laquelle, selon que le groupe d'images d'origine ou ultérieur était supérieur ou inférieur au remplacement souhaité, une Une erreur d'assertion se produit qui dit: 

*** Assertion failure in -[UICollectionViewData validateLayoutInRect:], 
/SourceCache/UIKit_Sim/UIKit-2891.1/UICollectionViewData.m:341
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
reason: 'UICollectionView recieved layout attributes for a cell with an 
index path that does not exist: <NSIndexPath: 0xb141c60> {length = 2, path = 0 - 2}

Dans ce cas, la liste existante du nombre d'images était 5 et la nouvelle liste d'images était donc 2. Ainsi, lorsqu'elle est arrivée à la troisième image - une exception s'est produite - indiquant que l'interface utilisateur CollectionViewDataDelegate n'était pas au courant du changement apporté au flux de données. . 

Des suggestions sur la manière de vous assurer que les nouvelles images seront référencées par UICollectionView? Bien sûr, j'ai appelé 'reloadData'… 

Je vous remercie

59
user1686700

Je cours dans le même problème. Le code fonctionne sous 6.1 et se bloque sous 7.0 J'ai résolu le problème de la manière suivante:

Dans la fonction 

-(NSInteger) numberOfSectionsInCollectionView:(UICollectionView *)collectionView

J'appelle

[myCollectionView.collectionViewLayout invalidateLayout];

C'est tout.

84
Dominic Sander

Avec iOS 10 et 11, cela aide:

collectionView.reloadData()
collectionView.collectionViewLayout.invalidateLayout()

La disposition invalide doit être APRÈS le rechargement des données.

22
Michał Kwiecień

Dominic Sander et user1544494 ont raison et leurs solutions sont bonnes.

Malheureusement, j'ai remarqué que si vous définissez minimumLineSpacingForSectionAtIndex ou minimumInteritemSpacingForSectionAtIndex, l'apparence de votre collectionView va se rompre (tôt ou tard).

Mettre invalidateLayout dans viewWillLayoutSubviews répond à cette question et aide à préserver l'aspect de viewCollection.

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    [viewCollection.collectionViewLayout invalidateLayout];
}
21
Beppe

C'est simple ... juste comme la phrase ci-dessous. 

'UICollectionView recieved layout attributes for a cell with an 
index path that does not exist: <NSIndexPath: 0xb141c60> {length = 2, path = 0 - 2}

Cela signifie qu'il n'y a pas indexPath (0,2) sur dataSouce . Mais votre UICollectionViewLayout renvoie un UICollectionViewLayoutAttributes pour indexPath (0,2).

Vous devez renvoyer UICollectionViewLayoutAttributes uniquement existant sur dataSouce.


Je pense que cela a changé de iOS7.

12
TopChul

Mon problème était que j'avais deux UICollectionViews dans une UIViewController. Et j’avais les deux UICollectionViews connectés à la même sous-classe UICollectionViewLayout. J'ai résolu ce problème en modifiant chaque UICollectionView pour avoir sa propre sous-classe UICollectionViewLayout.

Source: Cette question

10
Johann Burgess

J'ai résolu ce problème en mettant à jour la source de données de ma vue de collection:

- (NSInteger)collectionView:(UICollectionView *)collectionView
     numberOfItemsInSection:(NSInteger)section
{
    [collectionView.collectionViewLayout invalidateLayout];
    return collectionArray.count;
}
4
megha

J'ai rencontré ce problème après avoir modifié le contenu de la vue Collection. La solution qui a fonctionné dans mon cas était d'invalider la mise en page après le rechargement. Le faire avant le rechargement ne fonctionnera pas.

[collectionView reloadData];

//forces the layout attributes to be recalculated for new data
[collectionView.collectionViewLayout invalidateLayout];
2
ricosrealm

La solution que j'ai trouvée consistait à vérifier que la variable indexPath que je créais dans la méthode layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? était valide pour la ligne. Auparavant, j'utilisais (où i est mon compteur de boucles):

var indexPath = NSIndexPath(index: i)
var attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)

Mais le mettre à jour pour utiliser ce qui suit l'a résolu:

var indexPath = NSIndexPath(forRow: i, inSection: 0)!
var attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
1
Sam Youtsey

J'ai pu résoudre ce problème en créant une sous-classe de UICollectionViewFlowLayout et en surchargeant cette méthode pour renvoyer YES:

- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds
{
    return YES;
}
1
Snowman

J'ai rencontré quelque chose de similaire lorsque j'essayais de dupliquer une vue de collection dans un autre storyboard.

'UICollectionView a reçu des attributs de mise en page pour une cellule avec un index chemin qui n'existe pas: {longueur = 2, chemin = 1 - 0} '

Au début, je cherche une solution rapide. Essayé copier coller différentes réponses StackOverflow.

Mais j'ai écrit mon propre cours de mise en page. J'essaie donc de déboguer discrètement, cela pourrait être ma mise en cause, non? Constaté que la méthode numberOfSections n'a jamais été appelée. La vue de collection supposait qu’elle n’avait qu’une section.

Ensuite, j'ai trouvé que la classe du contrôleur de vue avait oublié de se conformer à UICollectionViewDataSource. Bien que la source de données soit connectée au storyboard, la classe du contrôleur de vue sera probablement downcast, comme if let ds = dataSource as? UICollectionViewDataSource {ds.numberOfSections...}, qui échouerait en mode silencieux.

J'ai donc ajouté la conformité à UICollectionViewDataSource et tout fonctionne bien. Mon hypothèse pourrait être inexacte. Mais la leçon à tirer est qu’à chaque fois qu’un bogue dont vous n’êtes pas familier se lève, installez-vous et comprenez-le.UICollectionView a reçu les attributs de mise en forme pour une cellule dont le chemin d'index n'existe pas, cela signifie exactement ce qu'il dit. Pas si dur que ça? N'essayez pas de trouver une solution miracle, comme beaucoup de réponses ici. Ils sont tous excellents mais votre code est le véritable lieu de bataille.

0
jchnxu

Dans mon cas, j'avais une coutume UICollectionViewFlowLayout. Après avoir supprimé les cellules de la collection, l'application s'est écrasée. Le correctif était de removeAll() attributs précédemment calculés. Ainsi, la première ligne après override func prepare() est arrayHoldingYourAttributes.removeAll()

0
Pantelis Proios

J'ai rencontré ce problème et c'était assez énervant. Ma solution est d'oublier UICollectionViewController et d'utiliser à la place des UIViewController ordinaires avec des UICollectionView à l'intérieur.

0
Pavel Sharanda

Cela signifie qu'il n'y a pas indexPath (0,2) sur dataSouce. Cependant, votre UICollectionViewLayout renvoie un UICollectionViewLayoutAttributes pour indexPath (0,2). Par TopChul

C'est vrai! Pour moi, le problème est dû au fait que j'utilise la même disposition de collection (instance) pour deux collectionView! Donc, cette mise en page confondue entre deux vues de collection.

Cela fonctionne bien après que j'utilise une disposition différente entre différentes vues de collection.

0

J'ai aussi eu ce bogue et j'ai trouvé une solution de contournement. Pour moi, UICollectionView le lançait sous iOS 7, fonctionnant parfaitement sous iOS 8.

Consultez cet article: Qu'est-ce qui cause ce crash iOS? UICollectionView a reçu des attributs de mise en page pour une cellule avec un chemin d'index inexistant

En 2 mots: Mise en page automatique. Désactivez-le sur la vue contenant UICollectionView et pour moi, cela a fonctionné.

0
Eric Giguere

Assurez-vous de mettre à jour la contentSize de votre collectionViewLayout. Ainsi, après avoir obtenu de nouvelles images (2 au lieu de 5), recalculez la variable contentSize et définissez-la.

0

J'ai eu un problème similaire (en utilisant Swift2.0, XCode 7).

L'application s'est écrasée avec UICollectionView received layout attributes for a cell with an index path that does not exist...

Dans mon cas, depuis que j'ai utilisé le storyboard, il s'est avéré que j'avais oublié de connecter l'IBOutlet défini dans mon viewController avec la collection collectionView définie dans le storyboard. Connecter les deux a résolu le problème.

0
da-na

Je rencontre le même problème lorsque j'utilise UICollectionViewFlowLayout en tant que CollectionView's collectionViewLayout

Déclarer le parent viewController implémenté UICollectionViewDelegateFlowLayout et l'affecter comme délégué collectionView peut résoudre ce problème. 

0
ChaoTangChang

Je l'ai compris . Si vous utilisez nib/xib pour organiser vos UITableViewCell et niché UICollectionView, vous pouvez éviter cette erreur en surchargeant cette méthode.

- (void)prepareForReuse {

    [super prepareForReuse];
    [self.collectionView.collectionViewLayout invalidateLayout];
}

J'espère que ça aide.

0
tounaobun

CollectionViewLayout met en cache les attributs de présentation . Créez une nouvelle instance de collectionViewLayout et affectez-la à collectionview.collectionViewLayout. Cela a fonctionné pour moi, en particulier lorsque vous utilisez d'autres bibliothèques collectionViewLayout.

0
Ankish Jain