報錯 Assertion failure in -[UICollectionViewData invalidateItemsAtIndexPaths:]
近來偶爾用到UICollectionView,對於九宮格之類的布局還是很方便的。但使用過程中卻出現一個奇怪的問題,暫時沒時間仔細研究。先記錄。
在UICollectionViewCell中定義一個圖標和一個文本,顯示的效果是典型的九宮格。默認會有幾條數據,點擊最后一個cell會彈出編輯框添加自定義的cell。使用過程中出現的問題時,在第二行最后一個添加的自定義cell,圖標怎么都改變不了。如果將整個view切換一下,顯示又變成正常了。如下圖:
查看打印出來的數據,是正常的。如下:
( { index = 0; name = "\U5915\U9633"; thumb = "sunset_btn_nor"; }, { index = 1; name = "\U665a\U9910"; thumb = "dinner_btn_nor"; }, { index = 2; name = "\U770b\U7535\U89c6"; thumb = "tv_btn_nor"; }, { index = 3; name = "\U6e29\U548c"; thumb = "soft_btn_nor"; }, { index = 4; name = "\U51b7\U5149"; thumb = "coldlight_btn_nor"; }, { index = 5; name = night; thumb = "my_btn_nor"; }, { index = 6; name = morning; thumb = "my_btn_nor"; }, { index = 7; name = sunset; thumb = "my_btn_nor"; }, { index = 8; name = "\U81ea\U5b9a\U4e49"; thumb = "add_btn_nor"; } )
添加斷點,發現數據也沒有問題。代碼的處理方式是在插入或者更新數據后,調用
[collectionView reloadData];
的方法。
網上搜索,也看到有人問類似的問題。有些人給出的解決辦法是加一個空的UIView在上面,強制整個collection view刷新。但感覺不是好的辦法。
后來試了更新指定項,問題就不出現了。
以下兩種方法均有效:
[self.collectionViewreloadItemsAtIndexPaths:@[[NSIndexPathindexPathForRow:7inSection:0]]];
或者
[self.collectionViewreloadSections:[NSIndexSetindexSetWithIndex:0]];
至於為什么reloadData會無效。這個暫時留下,等有空的時候再研究一下其原理。或者有牛人知道也請不吝賜教。
另外,這情況也提醒我們,能確定加載某個子項的,還是調用直接刷新指定項更好。一來效率高,二來避免出現莫名其妙的現象。
==================
昨天的問題補充一下。發現不是reloadData的問題。后來在測試中,使用reloadSections也會出現問題。
跟蹤了一下,發現在reloadData過程中,最后一個(也就是新增加)的一個cell沒有調用layoutSubviews。因為是在layoutSubviews中改變custom cell的image和label的值,所以新增加的cell沒有刷新。后來換成了在賦值過程中調用更新image和label的代碼,這樣無論reloadData和reloadSections都有效了,因為這樣保證了加載數據的時候imageView和label都被調用。或者也可以在cellForRowAtIndexPath中調用[cell setNeedsLayout];去強制調用layoutSubviews,這樣也達到更新的效果。
但是有點比較奇怪的是,之前的uitableview和uicollectionview自定義cell都是在layoutSubviews里面更新對應的控件,卻沒出現過問題。是不是iOS7以后,加載的機制發生變化了。這個有待進一步研究。
今天查找資料的時候,順便收集了一個圖表,圖表清楚說明了會引起調用layoutSubviews的操作。(x表示被調用)