UIImagePickerController选择/取消按钮无法点击、选择图片后交互失效问题求助
根据你提供的错误日志和代码,问题的核心有两个关键原因,我们一步步来解决:
1. 未处理「未编辑图片」的场景,导致选择器无法正常关闭
你的imagePickerController(_:didFinishPickingMediaWithInfo:)方法中,只尝试获取.editedImage(编辑后的图片),但如果用户直接选择原图、没有进入编辑界面,这个key对应的value会是nil。此时guard let会直接return,导致dismiss(animated: true)没有被调用——选择器既不关闭,还会因为系统回调未正常完成,触发XPC连接异常。
2. 保存图片的URL缺少文件扩展名,触发NSURL异常
错误日志里的-[NSURL URLByAppendingPathExtension:]: component, components, or pathExtension cannot be nil,是因为你保存JPEG格式的图片时,只使用了UUID作为文件名,没有添加.jpg扩展名。系统内部处理该文件路径时,可能尝试为URL补全扩展名但传入了nil,从而抛出异常,直接导致XPC连接失效,选择器彻底失去响应。
具体修复步骤:
① 同时兼容编辑图和原图,确保选择器总能关闭
在获取图片时,优先取.editedImage,如果不存在则降级取.originalImage,就算最终无法获取图片,也要保证选择器被关闭。
② 为图片路径添加正确的扩展名
保存JPEG数据时,给文件名加上.jpg后缀,保证URL格式完全符合系统要求。
③ 补充相册授权的「未确定状态」处理
当前代码在相册授权状态为.notDetermined时直接return,会导致首次使用的用户点击「从相册上传」后无反应,需要添加请求授权的逻辑。
修改后的关键代码示例:
修复UIImagePickerControllerDelegate方法
extension AddPhotoSceneViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { // 优先取编辑图,没有则取原图;两者都取不到则关闭选择器 guard let image = info[.editedImage] as? UIImage ?? info[.originalImage] as? UIImage else { dismiss(animated: true) return } // 为JPEG图片添加.jpg扩展名 let imageName = "\(UUID().uuidString).jpg" let imagePath = getDocumentsDirectory().appendingPathComponent(imageName) if let jpegData = image.jpegData(compressionQuality: 0.8) { try? jpegData.write(to: imagePath) } self.imageView.image = image self.setRightNavBarButtonView(title: "Next", target: self, selector: #selector(self.routeToAddPhotoForm)) dismiss(animated: true) } func getDocumentsDirectory() -> URL { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) return paths[0] } }
修复相册授权的未确定状态处理
let uploadFromGalleryAction = UIAlertAction(title: "Upload photo from gallery", style: .default) { (action) in self.picker.sourceType = .photoLibrary switch PHPhotoLibrary.authorizationStatus(){ case .authorized: self.invokePicker() case .denied: let modalView = ModalPopUpViewController(title: "Access Denied", text: "If you want to upload your own photo we need your access to open gallery", buttontext: "Open Settings", action: #selector(self.openSettings), target: self) self.present(modalView, animated: true, completion: nil) case .notDetermined: // 首次使用时请求相册授权,授权通过后再打开选择器 PHPhotoLibrary.requestAuthorization { status in if status == .authorized { DispatchQueue.main.async { self.invokePicker() } } } default: return } }
完成这些修改后,选择器点击「选择」或「取消」按钮的交互会恢复正常,也能避免因路径格式问题触发的系统异常。
内容的提问来源于stack exchange,提问作者Ivanius

