UICollectionView reload后本地图片位置错乱问题求助
UICollectionView reloadData后本地图片位置错乱的解决方案
这个问题我太熟悉了,本质是UICollectionView的cell复用机制没处理好!当你调用reloadData或者滚动列表时,系统会复用之前创建过的cell,如果没在复用的时候重置cell中控件的状态,就会出现控件状态错乱的情况。
看你的代码,问题出在lockImg的状态没有被重置:比如某个cell之前因为playable == 1被设置为isHidden = true,当它被复用到一个需要显示lockImg的位置时,isHidden还是true,就会导致图片不显示;反之,之前显示lockImg的cell被复用到需要隐藏的位置时,图片依然会显示,最终表现为位置错乱。
解决这个问题的核心是:在为cell设置新数据前,先重置所有可能影响显示的控件状态,让cell回到初始状态,再根据当前indexPath的数据设置正确的属性。
修改后的代码如下:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { // 用guard let安全解包cell,避免强制解包导致崩溃 guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SongCollectionViewCell", for: indexPath) as? SongCollectionViewCell else { return UICollectionViewCell() } let getArtistOfWeekObject = self.getArtistOfWeekObjectList?.game?.locks?[indexPath.row] print(getArtistOfWeekObject as Any) // 先重置lockImg的状态,消除复用带来的残留影响 cell.lockImg.isHidden = false cell.lockImg.image = nil // 也可以设置一张默认占位图,根据你的需求调整 // 再根据当前数据设置对应状态 if getArtistOfWeekObject?.status == 1 { cell.lockImg.image = #imageLiteral(resourceName: "select") cell.numberLbl.text = "song \(indexPath.row + 1)" } else if getArtistOfWeekObject?.playable == 1 { cell.lockImg.isHidden = true cell.numberLbl.text = "song \(indexPath.row + 1)" } else { cell.lockImg.image = #imageLiteral(resourceName: "white_lock") cell.numberLbl.text = "song \(indexPath.row + 1)" } return cell }
额外的优化建议:
- 把代码里的
songListCollectionView换成参数传入的collectionView,这样如果以后有多个UICollectionView,代码也能正常工作,符合苹果的数据源协议规范。 - 避免使用强制解包
!,用guard let或者if let处理可选类型,减少崩溃风险。
内容的提问来源于stack exchange,提问作者vandana
相关产品推荐
相关产品推荐

