Swift中UIImagePickerController拍照后无法显示预览的问题
相机拍照后图片无法显示在UIImageView的问题排查与解决
问题场景
Swift开发中,界面包含两个图片控件profilePicImage和rightProfilePicImg,通过ImageChooser枚举标记用户点击的按钮。当前实现下,从相册选择图片可正常显示到对应控件,但调用相机拍照后,图片无法显示在控件内(不过图片值能正常传入JSON参数)。
相关代码
enum ImageChooser {case profile,right} let imagePickerEdit = UIImagePickerController() var chooser:ImageChooser = .profile @IBAction func profilePicBtn(_ sender: UIButton) { chooser = .profile } @IBAction func rightProfileBtn(_ sender: UIButton) { chooser = .right let alert = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet) alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: { _ in self.openCamera() })) alert.addAction(UIAlertAction(title: "Gallery", style: .default, handler: { _ in self.openGallery() })) alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil)) self.present(alert, animated: true, completion: nil) } @IBAction func profilePicBtn(_ sender: UIButton) { chooser = .profile let alert = UIAlertController(title: "Choose Image", message: nil, preferredStyle: .actionSheet) alert.addAction(UIAlertAction(title: "Camera", style: .default, handler: { _ in self.openCamera() })) alert.addAction(UIAlertAction(title: "Gallery", style: .default, handler: { _ in self.openGallery() })) alert.addAction(UIAlertAction.init(title: "Cancel", style: .cancel, handler: nil)) self.present(alert, animated: true, completion: nil) } func openCamera() { if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) { imagePickerEdit.delegate = self imagePickerEdit.sourceType = UIImagePickerController.SourceType.camera imagePickerEdit.allowsEditing = false self.present(imagePickerEdit, animated: true, completion: nil) } else { let alert = UIAlertController(title: "Warning", message: "You don't have camera", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) self.present(alert, animated: true, completion: nil) } } func openGallery() { if UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary){ // let imagePicker = UIImagePickerController() imagePickerEdit.delegate = self imagePickerEdit.allowsEditing = true imagePickerEdit.sourceType = UIImagePickerController.SourceType.photoLibrary self.present(imagePickerEdit, animated: true, completion: nil) } else { let alert = UIAlertController(title: "Warning", message: "You don't have permission to access gallery.", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) self.present(alert, animated: true, completion: nil) } } extension NewEditProfileViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { if let pickedImage = info[.originalImage] as? UIImage { if chooser == .profile { profilePicImage.image = pickedImage } if chooser == .right { rightProfilePicImg.image = pickedImage } } picker.dismiss(animated: true, completion: nil) } }
问题原因分析
- 重复的IBAction方法:存在两个同名的
profilePicBtnIBAction,会导致按钮关联异常,编译时出现警告,可能造成逻辑执行混乱。 - UI更新未确保在主线程:相机拍照后的回调可能在非主线程执行,直接更新UIImageView的
image属性会导致UI无法刷新(相册选择的回调通常在主线程,所以能正常显示)。 - 全局UIImagePickerController复用的潜在问题:全局复用
imagePickerEdit时,每次打开相机/相册未完全重置配置,可能导致参数冲突。
解决步骤
1. 删除重复的IBAction方法
保留包含弹窗逻辑的profilePicBtn方法,删除仅设置chooser的同名方法,确保按钮点击能正确弹出选择菜单并设置对应的chooser值。
2. 确保UI更新在主线程执行
在代理方法中更新UIImageView时,强制切换到主线程:
extension NewEditProfileViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate { func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { picker.dismiss(animated: true) { // 确保在主线程更新UI DispatchQueue.main.async { if let pickedImage = info[.originalImage] as? UIImage { if self.chooser == .profile { self.profilePicImage.image = pickedImage } else if self.chooser == .right { self.rightProfilePicImg.image = pickedImage } } } } } }
3. 优化UIImagePickerController的使用
避免全局复用,改为每次打开相机/相册时创建新的实例,防止配置冲突:
// 删除全局的imagePickerEdit,改为在方法内创建 func openCamera() { if UIImagePickerController.isSourceTypeAvailable(.camera) { let imagePicker = UIImagePickerController() imagePicker.delegate = self imagePicker.sourceType = .camera imagePicker.allowsEditing = false self.present(imagePicker, animated: true) } else { let alert = UIAlertController(title: "Warning", message: "You don't have camera", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default)) self.present(alert, animated: true) } } func openGallery() { if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) { let imagePicker = UIImagePickerController() imagePicker.delegate = self imagePicker.allowsEditing = true imagePicker.sourceType = .photoLibrary self.present(imagePicker, animated: true) } else { let alert = UIAlertController(title: "Warning", message: "You don't have permission to access gallery.", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default)) self.present(alert, animated: true) } }
4. 统一判断逻辑
将代理方法中的两个if改为else if,避免不必要的判断执行,提升代码效率。
内容的提问来源于stack exchange,提问作者anySwift
相关产品推荐
相关产品推荐

