如何让UIImagePickerController选拍图片传入DetailViewController?排查断言Bug
问题排查与修复方案
核心问题拆解
- 图片选择流程逻辑混乱:点击按钮后立刻弹出选择器,紧接着就跳转详情页+调用关闭操作,导致选择器刚显示就被关闭,用户根本无法选择/拍摄图片
- 代理关系错误:
UIImagePickerController的代理设置给了ViewController,但图片处理逻辑在DetailViewController,选图完成后的回调永远不会被详情页接收 - 强制解包触发断言崩溃:
currentFilter.outputImage!这类强制解包操作,在滤镜未正确初始化或无输出时会直接引发崩溃
修复后的ViewController代码
import UIKit class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate { @IBOutlet var takePicture: UIButton! @IBOutlet var editPhoto: UIButton! override func viewDidLoad() { super.viewDidLoad() } @IBAction func takePicture(_ sender: UIButton) { presentImagePicker(sourceType: .camera) } @IBAction func editPhoto(_ sender: UIButton) { presentImagePicker(sourceType: .photoLibrary) } // 统一封装图片选择器逻辑 private func presentImagePicker(sourceType: UIImagePickerController.SourceType) { guard UIImagePickerController.isSourceTypeAvailable(sourceType) else { // 处理设备不支持的情况(比如模拟器无法调用相机) let alert = UIAlertController(title: "提示", message: "当前设备无法使用该功能", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "确定", style: .default)) present(alert, animated: true) return } let picker = UIImagePickerController() picker.sourceType = sourceType picker.allowsEditing = true picker.delegate = self present(picker, animated: true) } // 选图完成后跳转详情页并传递图片 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { picker.dismiss(animated: true) guard let editedImage = info[.editedImage] as? UIImage else { print("未获取到有效图片") return } // 初始化详情页并传入图片 if let detailVC = storyboard?.instantiateViewController(withIdentifier: "Detail") as? DetailViewController { detailVC.currentImage = editedImage navigationController?.pushViewController(detailVC, animated: true) } } // 用户取消选图的回调 func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { picker.dismiss(animated: true) } }
修改点说明
- 移除了混乱的
actionClose和多余的关闭调用,统一在选图完成/取消时处理选择器的关闭 - 封装
presentImagePicker方法,避免重复代码,同时增加设备兼容性判断 - 将跳转详情页的逻辑移到选图完成回调中,确保只有选到图片后才跳转,并直接传递图片数据
修复后的DetailViewController代码
import UIKit import CoreImage class DetailViewController: UIViewController { @IBOutlet var imageView: UIImageView! @IBOutlet var slider1: UISlider! @IBOutlet var slider2: UISlider! @IBOutlet var slider3: UISlider! @IBOutlet var slider4: UISlider! // 改为可选类型,避免未初始化的断言问题 var currentImage: UIImage? var context: CIContext! var currentFilter: CIFilter! override func viewDidLoad() { super.viewDidLoad() title = "Photo Editor" context = CIContext() currentFilter = CIFilter(name: "CISepiaTone") // 视图加载完成后处理传入的图片 if let image = currentImage { setupFilter(with: image) } } private func setupFilter(with image: UIImage) { guard let ciImage = CIImage(image: image) else { return } currentFilter.setValue(ciImage, forKey: kCIInputImageKey) // 给滤镜设置默认参数(CISepiaTone默认强度为0,无效果) currentFilter.setValue(0.5, forKey: kCIInputIntensityKey) applyProcessing() } func applyProcessing() { guard let outputImage = currentFilter.outputImage else { return } if let cgimg = context.createCGImage(outputImage, from: outputImage.extent) { let processedImage = UIImage(cgImage: cgimg) imageView.image = processedImage } } }
修改点说明
- 移除了多余的选择器代理实现,详情页不再负责弹出选择器
- 将
currentImage改为可选类型,避免未初始化导致的断言崩溃 - 在
viewDidLoad中处理传入的图片,初始化滤镜并应用默认效果 - 把强制解包改为可选绑定,避免空值引发的崩溃
内容的提问来源于stack exchange,提问作者lion 8w7
相关产品推荐
相关产品推荐

