Swift 如何将UICollectionView默认图片替换为PHPicker选中的用户照片
问题根源
你之前的写法存在两个核心问题:
- 使用
insert(at: 0)会给数组新增元素,数组长度持续增加,导致CollectionView多出额外的Cell - 先删除首位再插入的逻辑只会固定修改第0位元素,后续选中的图片永远只会替换第一个Cell
解决方案
我们固定数据源数组的长度始终为3,选中图片时找到第一个未被替换的默认图位置直接替换即可,删除图片时还原对应位置为默认图:
- 先定义固定的默认图常量作为还原依据
// 固定的默认图片数组,删除时用来还原 private let defaultImages = [ UIImage(systemName: "camera"), UIImage(systemName: "photo"), UIImage(systemName: "photo") ] // 实际使用的数据源数组,初始化直接使用默认图 var imgArray = defaultImages
- 修改PHPicker选中回调的逻辑
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { dismiss(animated: true) // 计算第一个可替换的位置:找到第一个和默认图一致的下标 var firstReplaceIndex = 0 for (index, image) in imgArray.enumerated() { if image == defaultImages[index] { firstReplaceIndex = index break } // 所有位置都已替换完成直接返回 if index == imgArray.count - 1 { return } } // 按选中顺序给每张图片绑定要替换的目标下标 for (offset, item) in results.enumerated() { let targetIndex = firstReplaceIndex + offset // 超出数组最大长度直接终止 guard targetIndex < imgArray.count else { break } item.itemProvider.loadObject(ofClass: UIImage.self) { [weak self] image, error in guard let self = self, let image = image as? UIImage else { return } DispatchQueue.main.async { // 直接替换对应位置的元素,无需插入/删除 self.imgArray[targetIndex] = image self.collectionView.reloadData() } } } }
- 删除图片的逻辑
// 传入要删除的Cell对应的下标即可 func deleteImage(at index: Int) { imgArray[index] = defaultImages[index] collectionView.reloadData() }
优化建议
如果担心异步加载图片导致顺序错乱,可以用DispatchGroup等所有选中的图片全部加载完成后,再按顺序批量替换数据源,最后刷新列表。
内容的提问来源于stack exchange,提问作者ronix
相关产品推荐
相关产品推荐

