使用PHPicker时,重新打开照片库后如何处理照片取消选择?
解决PHPicker取消选择图片时的数组更新问题
你的核心问题在于:PHPicker的didFinishPicking回调返回的results是用户最终选中的所有图片集合,而非新增/取消的差异项。你之前直接追加图片的逻辑,会导致取消选择的图片依然留在selectedPhotos数组里。
修正思路
- 先通过返回的
results更新图片标识符数组imageIdentifierArray,这一步你已经做了。 - 基于最新的标识符数组,重新同步
selectedPhotos:先清空旧数组,再加载当前选中的所有图片;或者过滤掉不在新标识符列表里的旧图片(推荐前者,逻辑更清晰)。 - 不需要依赖
result.itemProvider.canLoadObject的判断来筛选,直接遍历所有results加载图片即可——因为results里只包含当前选中的项,取消的项根本不会出现在这里。
修正后的代码
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) { picker.dismiss(animated: true, completion: nil) // 更新标识符数组 let identifiers = results.compactMap(\.assetIdentifier) self.parent.imageIdentifierArray = identifiers // 先清空旧的选中图片数组,准备加载最新选中的内容 DispatchQueue.main.async { selectedPhotos.removeAll() } // 加载当前所有选中的图片 for result in results { guard result.itemProvider.canLoadObject(ofClass: UIImage.self) else { continue } result.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.selectedPhotos.append(image) // 如果需要刷新UI,这里可以调用tableView.reloadData()或者collectionView.reloadData() } } } }
额外说明
- 如果你不想每次都清空数组重新加载,也可以通过标识符对比来找出被取消的图片并删除:
不过这种方式需要额外维护图片和标识符的映射,不如直接清空重新加载简单可靠,尤其是在图片数量不多(你设置了最多4张)的情况下,性能影响可以忽略。// 在更新identifiers之后 DispatchQueue.main.async { // 过滤掉不在新标识符列表里的图片 self.selectedPhotos = self.selectedPhotos.filter { image in // 这里需要你额外维护图片和标识符的对应关系,比如用字典存储[assetIdentifier: UIImage] // 假设你有一个photoMap: [String: UIImage]的字典 let identifier = self.photoMap.first { $0.value == image }?.key return identifier != nil && identifiers.contains(identifier!) } }
内容的提问来源于stack exchange,提问作者lex
相关产品推荐
相关产品推荐

