前兩天項(xiàng)目里遇到一個(gè)不太常見的collectionView的crash(標(biāo)題起這么長是為了方便遇到同樣問題的朋友能夠快速檢索到)
UICollectionView received layout attributes for a cell with an index path that does not exist:
<NSIndexPath: 0x80b1dc933cf8f0de> {length = 2, path = 0 - 4}
簡單翻譯一下:UICollectionView接收到了下標(biāo)不存在的cell的布局屬性。
結(jié)合項(xiàng)目具體crash的場景發(fā)現(xiàn):collectionView reloadData時(shí)叨吮,數(shù)據(jù)源已經(jīng)變了莺奸,但是cell的layout attributes還沒有更新惯疙,也就是collectionViewLayout出了故障邦危。
stackoverflow上看到很多人遇到了這個(gè)問題骂因,解決辦法五花八門方庭,我試了一圈在這個(gè)場景下基本沒用翩瓜。
說的最多的是在各個(gè)地方調(diào)用這句讓布局失效的代碼:
[self.collectionView.collectionViewLayout invalidateLayout];
這句代碼從理論上講應(yīng)該是可以起作用的跨扮,然而我試了沒什么卵用序无,后來我冷靜下來思考了一下,既然是要讓現(xiàn)有布局無效衡创,不如我直接重新alloc一個(gè)collectionViewLayout好了帝嗡。。
即每次刷新數(shù)據(jù)之前調(diào)一下這個(gè)方法
- (void)refreshFlowLayout
{
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc]init];
self.vipCollectionView.collectionViewLayout = flowLayout;
}
就解決了璃氢。丈探。
collectionViewLayout為什么會(huì)發(fā)生故障,這個(gè)暫時(shí)還沒有頭緒拔莱,stackoverflow上也沒人提到過碗降,下周過來再研究研究。
周一過來塘秦,又回頭看這個(gè)問題讼渊,恰巧同事lkk跟我說:“你是不是改了啥,某處在模擬器上一直崩潰”尊剔。
慌的一批爪幻,明明我的真機(jī)是不崩的,但是模擬器崩潰也是不能忍的,我也懶得管是否在部分版本系統(tǒng)上會(huì)崩潰了挨稿,直接回滾代碼仇轻,重新尋找新的解決方案。奶甘。
重新翻看stackoverflow的文章篷店,一條一條的看,終于看到一條讓我有所啟發(fā)的comment:
這邊的意思是說當(dāng)數(shù)據(jù)源發(fā)生變化的時(shí)候臭家,先改變了contentInset再reloadData的話疲陕,就會(huì)crash,反之先reloadData再改變contentInset則是安全的钉赁!
原因是改變contentInset會(huì)觸發(fā)collectionView的布局更新蹄殃,如果數(shù)據(jù)源改變時(shí)先改變contentInset(即先更新布局,再reloadData)你踩,layout attributes的數(shù)據(jù)和新的數(shù)據(jù)源不對(duì)應(yīng)诅岩,發(fā)生崩潰也就不奇怪了~
仔細(xì)看了下崩潰的相關(guān)代碼,發(fā)現(xiàn)確實(shí)有這個(gè)騷操作??
于是把改變contentInset的方法放在reloadData后面執(zhí)行就好了:
小結(jié):第一種解決方案是在沒有找到問題真正的根源時(shí)的無奈之舉(周五晚上沒吃晚飯的情況下带膜,fix到實(shí)在餓的撐不住了的臨時(shí)方案)吩谦。第二種方案則是刨根問底,尋找到問題的本源钱慢,從而對(duì)癥下藥逮京。項(xiàng)目開發(fā)中,還是要盡可能的采用第二種思路去解決問題束莫,否則項(xiàng)目的健壯性會(huì)越來越差懒棉。