Swift 4拍照异常咨询:photoOutput返回nil问题
解决两个ViewController复用摄像头代码时photoOutput返回nil的问题
刚接触Swift遇到这种问题太正常了,别慌!咱们一步步拆解排查:
1. 先检查对象生命周期——最容易踩的坑
很多新手会把AVCaptureSession或者AVCapturePhotoOutput写成函数里的局部变量,这样函数执行完,这些对象就被ARC自动释放了,等到要拍照时photoOutput自然就成了nil。
正确做法:把它们声明为ViewController的实例属性,确保在VC存活期间一直存在:
class YourSecondVC: UIViewController { // 声明为实例属性,别放在setupCamera这类函数里当临时变量 private let captureSession = AVCaptureSession() private var photoOutput: AVCapturePhotoOutput? override func viewDidLoad() { super.viewDidLoad() setupCamera() } private func setupCamera() { // 初始化photoOutput并添加到session photoOutput = AVCapturePhotoOutput() guard let output = photoOutput else { print("初始化photoOutput失败") return } if captureSession.canAddOutput(output) { captureSession.addOutput(output) } // 其他摄像头配置(设备选择、输入添加)... } }
2. 确认摄像头资源是否被占用
切换VC时,前一个VC的AVCaptureSession如果没停止,会一直占用摄像头设备,导致新VC无法正常初始化photoOutput。
解决步骤:
- 在每个VC的
viewWillDisappear里停止session,释放资源:
override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) if captureSession.isRunning { captureSession.stopRunning() } }
- 初始化摄像头时,确保正确选择目标设备(比如你第二个VC可能要用前置?):
private func getTargetCamera(position: AVCaptureDevice.Position) -> AVCaptureDevice? { let discoverySession = AVCaptureDevice.DiscoverySession( deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .unspecified ) return discoverySession.devices.first { $0.position == position } } // 在setupCamera里调用 guard let camera = getTargetCamera(position: .front) else { print("无法获取目标摄像头") return }
3. 检查代理设置是否到位
如果photoOutput的代理没设置,或者代理对象被释放,也会出现类似photoOutput无效的情况(甚至回调根本不执行)。
确保代理配置正确:
// 在setupCamera里,配置完photoOutput后设置代理 photoOutput?.setPreparedPhotoSettingsArray( [AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])], completionHandler: nil ) photoOutput?.delegate = self // 记得让VC遵守AVCapturePhotoCaptureDelegate协议
同时VC要实现协议扩展:
extension YourSecondVC: AVCapturePhotoCaptureDelegate { func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { // 处理拍摄后的照片逻辑... } }
4. 快速排查小技巧
在拍照按钮的点击事件里加个打印,确认状态:
@IBAction func takePhotoTapped(_ sender: UIButton) { print("photoOutput状态: \(photoOutput)") print("session是否运行: \(captureSession.isRunning)") guard let output = photoOutput, captureSession.isRunning else { print("摄像头未准备就绪") return } // 执行拍照逻辑... }
按照上面的步骤排查,大概率能解决问题。如果还是不行,可以把你的setupCamera和拍照代码贴出来,咱们再细抠!
内容的提问来源于stack exchange,提问作者Rolthar
相关产品推荐
相关产品推荐

