如何在UICollectionView的didSelectItemAt方法内弹出第二个操作提示框
实现方案
核心逻辑是在单元格选中回调中先判断当前person的名称状态:如果是图片刚导入时的默认值Unknown,走原有的首次命名流程;如果已经设置过人名,先弹出操作选择菜单,提供重命名、删除选项。
修改后的collectionView(_:didSelectItemAt:)完整代码
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let person = people[indexPath.item] // 判断是否是未命名的新导入图片 if person.name == "Unknown" { // 走原有的首次命名逻辑 let ac = UIAlertController(title: "给人物命名", message: nil, preferredStyle: .alert) ac.addTextField() ac.addAction(UIAlertAction(title: "取消", style: .cancel)) ac.addAction(UIAlertAction(title: "确定", style: .default) { [weak self, weak ac] _ in guard let newName = ac?.textFields?[0].text, !newName.isEmpty else { return } // 如果你的Person是struct类型,这里要改成 people[indexPath.item].name = newName person.name = newName self?.collectionView.reloadData() }) present(ac, animated: true) } else { // 已经命名过,弹出操作选择菜单 let actionSheet = UIAlertController(title: "操作选项", message: "你要对「\(person.name)」执行什么操作?", preferredStyle: .actionSheet) // 重命名选项 actionSheet.addAction(UIAlertAction(title: "重命名", style: .default) { [weak self] _ in // 复用原来的重命名弹窗逻辑 let renameAlert = UIAlertController(title: "重命名人物", message: nil, preferredStyle: .alert) renameAlert.addTextField() renameAlert.textFields?.first?.text = person.name renameAlert.addAction(UIAlertAction(title: "取消", style: .cancel)) renameAlert.addAction(UIAlertAction(title: "确定", style: .default) { [weak self, weak renameAlert] _ in guard let newName = renameAlert?.textFields?[0].text, !newName.isEmpty else { return } // 如果你的Person是struct类型,这里要改成 people[indexPath.item].name = newName person.name = newName self?.collectionView.reloadData() }) self?.present(renameAlert, animated: true) }) // 删除选项 actionSheet.addAction(UIAlertAction(title: "删除", style: .destructive) { [weak self] _ in // 1. 删除本地存储的图片文件 let imagePath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent(person.image) try? FileManager.default.removeItem(at: imagePath) // 2. 从数组中移除对应person self?.people.remove(at: indexPath.item) // 3. 刷新列表 self?.collectionView.reloadData() }) // 取消选项 actionSheet.addAction(UIAlertAction(title: "取消", style: .cancel)) // 适配iPad的弹出位置(可选,不加的话iPad上会崩溃) if let popoverController = actionSheet.popoverPresentationController { popoverController.sourceView = collectionView.cellForItem(at: indexPath) popoverController.sourceRect = collectionView.cellForItem(at: indexPath)?.bounds ?? .zero } present(actionSheet, animated: true) } }
注意点
- 如果你的
Person是值类型(struct),不能直接修改局部person变量的name属性,要直接修改数组对应位置的元素:people[indexPath.item].name = newName,否则修改不会生效 - 删除操作里加了本地图片的清理逻辑,避免无用文件占用沙盒存储空间
- 加了iPad的适配代码,避免在iPad上弹出actionSheet时崩溃
- 重命名弹窗默认填充了当前的人名,提升操作体验
内容的提问来源于stack exchange,提问作者George Beres
相关产品推荐
相关产品推荐

