報錯 Assertion failure in -[UICollectionViewData invalidateItemsAtIndexPaths:]佈局
近來偶爾用到UICollectionView,對於九宮格之類的佈局仍是很方便的。但使用過程當中卻出現一個奇怪的問題,暫時沒時間仔細研究。先記錄。測試
在UICollectionViewCell中定義一個圖標和一個文本,顯示的效果是典型的九宮格。默認會有幾條數據,點擊最後一個cell會彈出編輯框添加自定義的cell。使用過程當中出現的問題時,在第二行最後一個添加的自定義cell,圖標怎麼都改變不了。若是將整個view切換一下,顯示又變成正常了。以下圖:ui
查看打印出來的數據,是正常的。以下:spa
( { 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"; } )
添加斷點,發現數據也沒有問題。代碼的處理方式是在插入或者更新數據後,調用code
[collectionView reloadData];blog
的方法。it
網上搜索,也看到有人問相似的問題。有些人給出的解決辦法是加一個空的UIView在上面,強制整個collection view刷新。但感受不是好的辦法。io
後來試了更新指定項,問題就不出現了。table
如下兩種方法均有效:class
[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表示被調用)