iOS 10的bug:UICollectionView收到一个索引path不存在的单元格的布局属性

在iOS 10的设备上运行我的应用程序我得到这个错误:

UICollectionView收到一个索引path不存在的单元格的布局属性

在iOS 8和9工作正常。 我一直在研究,我发现这是相关的无效的集合视图布局。 我试图实现这个解决scheme没有成功,所以我想要求直接的帮助。 这是我的层次结构视图:

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

我试过的是插入

  [self.collectionView.collectionViewLayout invalidateLayout]; 

在里面

 - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView 

的收集意见。

此外,我已经尝试在做一个重载数据之前使布局无效,不起作用…

任何人都可以给我一些方向吗?

collectionView中的单元格数量发生变化时,发生了这种情况。 原来我在调用reloadData之后丢失了invalidateLayout。 join后,我没有再遇到任何崩溃。 Apple在iOS10中对collectionView进行了一些修改。 我想这就是为什么我们没有遇到旧版本相同的问题。

这是我的最终代码:

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

我也在同一视图中遇到了2个collectionView,因为我在两个集合中添加了相同的UICollectionViewFlowLayout:

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

当然,如果collectionView1数据发生变化,它会在重载数据上崩溃。 如果这可以帮助某人。

以前的答案有帮助,但如果您使用自动调整单元格,则其大小将不正确。

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

我通过replace来解决这个问题

 [self.collectionView reloadData]; 

 [self.collectionView reloadSections:indexSet]; 

当你有自定义的布局,记得清除caching(UICollectionViewLayoutAttributes),而重写准备func

  override func prepare() { cache.removeAll() 

每次都不是最好的重载(你应该使用insertItems和deleteItems,甚至reloadSections)。 但是……在说过某些情况下这是有效的,你可以这样做:

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

我也有这个问题。 在我的情况下,有一个自定义的UICollectionViewLayout应用到集合视图&问题是,它有陈旧的数据应该显示的单元格的数量。 当你看到UICollectionView received layout attributes for a cell with an index path that does not exist时,你肯定可以检查

@ Katrin的答案帮助了很多,但是我可以通过添加一行来获得更好的结果:

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

现在我不能说是否可以用这条线来重现崩溃,但是我猜想有一个……所以,仍然不是一个银弹,而是一些东西。

如果你想保持你的滚动位置和修复崩溃,你可以使用这个:

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