报错 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表示被调用)