代码创建UICollectionView后如何替换指定单元格内的UIImage图片
解决方案
第一步:先修复现有代码的复用隐患
你当前的实现存在单元格复用问题:全局的imageView2每次渲染单元格都会被重复添加到cell上,会导致图片叠加、后续修改出错,建议先自定义UICollectionViewCell子类统一管理图片控件:
// 自定义UICollectionViewCell子类 class MyCollectionViewCell: UICollectionViewCell { // 内置图片控件 let paleteImageView: UIImageView = { let imgView = UIImageView() imgView.contentMode = .scaleAspectFit imgView.clipsToBounds = true imgView.translatesAutoresizingMaskIntoConstraints = false return imgView }() override init(frame: CGRect) { super.init(frame: frame) contentView.addSubview(paleteImageView) // 约束设置,可根据需求调整 NSLayoutConstraint.activate([ paleteImageView.topAnchor.constraint(equalTo: contentView.topAnchor), paleteImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor), paleteImageView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), paleteImageView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor) ]) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
调整原有业务代码适配自定义cell:
var imagesOfPaletes = [UIImage]() override func viewDidLoad() { super.viewDidLoad() // 注册自定义cell,不可遗漏 collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: "MyCell") if imagesOfPaletes.isEmpty { for i in 0...11 { let palete = UIImage(named: "\(i)-0")! imagesOfPaletes.append(palete) } } } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! MyCollectionViewCell myCell.paleteImageView.image = imagesOfPaletes[indexPath.item] return myCell }
第二步:修改指定位置单元格的图片
推荐优先使用「修改数据源+局部刷新」的方案,避免单元格复用导致的修改失效问题:
- 先修改数据源数组对应位置的图片
- 局部刷新对应索引的单元格,系统会自动渲染新图片
// 替换为你要修改的单元格索引 let targetItemIndex = 3 let targetSectionIndex = 0 // 只有1个分组时固定为0 let newImage = UIImage(named: "替换的图片名")! // 1. 更新数据源 imagesOfPaletes[targetItemIndex] = newImage // 2. 局部刷新对应单元格 collectionView.reloadItems(at: [IndexPath(item: targetItemIndex, section: targetSectionIndex)])
如果确实需要直接获取当前可视区域内的单元格对象、读取/修改内部UIImage,可以用以下方式:
let targetIndexPath = IndexPath(item: targetItemIndex, section: targetSectionIndex) if let targetCell = collectionView.cellForItem(at: targetIndexPath) as? MyCollectionViewCell { // 获取当前单元格内的UIImage对象 let currentImage = targetCell.paleteImageView.image // 直接修改图片 targetCell.paleteImageView.image = newImage }
注意:该方法仅能获取到当前显示在屏幕上的单元格,若目标单元格已滑出屏幕会返回nil,且直接修改单元格不会同步数据源,滑出后再滑回会恢复为原图片。
内容的提问来源于stack exchange,提问作者SashDing
相关产品推荐
相关产品推荐

