我们的项目中有一个相对复杂的页面,如下图
我的处理方式是将整个下部写成一个UICollectionView,“单选题 本大题共。。。”和“算法的。。”作为cell,其他元素作为header和footer。由于下方淡蓝色的cell宽度是自适应的,逻辑是cell的宽度根据cell的内容来自适应,并且不能超过一定数值,否则lable添加“...”。
这个需求很快就想到了使用Autolayout的自适应Cell,我们只要设定好cell的约束,其他的布局就交给Autolayout来做。
let flowLayout = UICollectionViewLeftAlignedLayout()
flowLayout.estimatedItemSize = CGSize(width: 125, height: 40)
self.collectionView.collectionViewLayout = flowLayout
这个页面上面有左右切换按钮,点击之后会刷新UICollectionView的数据。进入页面没有问题,但是切换数据,调用ReloaData()方法就会崩溃,崩溃信息为:
UICollectionView received layout attributes for a cell with an index path that does not exist
找了很久,没有找到解决的办法,但大概的原因可能是:
使用了Autolayout自适应Cell后,UICollectionView会自动生成相应cell的size,并缓存起来(重点)。当我们获取了新的数据并ReloaData后,UICollectionView会尝试去拿缓存起来的cell的size(目的是提高性能)。但是此时我们的数据源发生了改变,cell的个数也变了,因此出现了数组下标越界,也就崩溃了。
正确的方法是:
self.collectionView.reloadData()
self.collectionView.collectionViewLayout.invalidateLayout()
刷新数据后清空collectionViewLayout的缓存,让Autolayout重新计算UICollectionView的cell的size。这样就没有问题了。