You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:07:56