Fallo de iOS 10: UICollectionView recibió attributes de layout para una celda con una ruta de índice que no existe

Ejecutar mi aplicación en un dispositivo con iOS 10 obtengo este error:

UICollectionView recibió attributes de layout para una celda con una ruta de índice que no existe

En iOS 8 y 9 funciona bien. He estado investigando y he descubierto que hay algo relacionado con invalidar el layout de vista de colección. Traté de implementar esa solución sin éxito, así que me gustaría pedir ayuda directa. Esta es mi vista jerárquica:

->Table view ->Each cell of table is a custom collection view [GitHub Repo][1] ->Each item of collection view has another collection view 

Lo que he intentado es insert

  [self.collectionView.collectionViewLayout invalidateLayout]; 

En el

 - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView 

de ambas vistas de colección.

También he intentado invalidar el layout antes de hacer una recarga de datos, no funciona …

¿Podría alguien darme algunas instrucciones para tomar?

Esto me sucedió cuando cambió el número de celdas en collectionView. Resulta que me faltaba invalidateLayout después de llamar a reloadData. Después de agregarlo, no he experimentado más fallas. Apple ha realizado algunas modificaciones a collectionViews en iOS10. Creo que esa es la razón por la que no estamos experimentando el mismo problema en las versiones anteriores.

Aquí está mi código final:

 [self.collectionView reloadData]; [self.collectionView.collectionViewLayout invalidateLayout]; 

También me enfrenté a este problema con 2 collectionViews en la misma vista porque agregué el mismo UICollectionViewFlowLayout en ambas collections:

 let layout = UICollectionViewFlowLayout() collectionView1.collectionViewLayout = layout collectionView2.collectionViewLayout = layout 

Por supuesto, se cuelga al recargar datos si los datos de collectionView1 cambian. Si esto puede ayudar a alguien.

La respuesta anterior ayuda, pero si usa células autorizadoras, su tamaño será incorrecto.

  UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; layout.estimatedItemSize = CGSizeMake(60, 25); layout.itemSize = UICollectionViewFlowLayoutAutomaticSize; self.collectionView.collectionViewLayout = layout; 

Resuelvo estos problemas reemplazando

 [self.collectionView reloadData]; 

a

 [self.collectionView reloadSections:indexSet]; 

Cuando tenga un layout personalizado, recuerde borrar el caching (UICollectionViewLayoutAttributes) mientras anula la function prepar.

  override func prepare() { cache.removeAll() 

No es el mejor para volver a cargar datos cada vez (debe usar insertItems y deleteItems, e incluso reloadSections). Pero … después de decir que en algunos casos es válido así, en realidad puedes hacer esto:

 collectionView.dataSource = nil collectionView.delegate = nil /*... All changes here. ... */ collectionView.dataSource = self collectionView.delegate = self collectionView.reloadData() 

La respuesta de @ Katrin me ayudó mucho, pero pude lograr resultados aún mejores agregando una línea más:

 collectionView.reloadData() collectionView.collectionViewLayout.invalidateLayout() collectionView.layoutSubviews() // <-- here it is :) 

Ahora no puedo decir si podría reproducirse estrellarse con esta línea o no, pero creo que había una … Entonces, todavía no es una bala de plata, sino algo.

Si desea mantener su position de desplazamiento y corregir el locking, puede usar esto:

 collectionView.reloadData() let context = collectionView.collectionViewLayout.invalidationContext(forBoundsChange: collectionView.bounds) context.contentOffsetAdjustment = CGPoint.zero collectionView.collectionViewLayout.invalidateLayout(with: context)