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

使用AVCaptureSession拍摄照片报错:No active and enabled video connection

解决AVCapturePhotoOutput抛出"No active and enabled video connection"异常的问题

核心错误原因

你代码里的AVCaptureSession是Initialize方法的局部变量,方法执行完毕后就会被系统销毁,导致photoOutput失去了关联的活跃会话,调用capturePhoto时自然会提示没有有效的视频连接。这和你去掉预览层无关——预览层不是拍照的必要条件,它只是用来在UI上显示相机画面,只要捕获会话正常运行、输入输出关联正确,即使没有预览层也能完成拍照。

你遗漏的关键内容

  • 捕获会话的生命周期管理:必须把AVCaptureSession设为类的成员属性,保证它在类的生命周期内持续存在,而不是局部变量。
  • 相机权限申请:iOS要求访问相机前必须向用户申请权限,否则无法获取相机设备,后续流程会直接失败。
  • 可选的配置完善:可以明确指定照片输出的格式,避免潜在的格式兼容问题。

修正后的代码

import UIKit
import AVFoundation

class cPhotoCaptureNormal: NSObject, AVCapturePhotoCaptureDelegate {
    private let photoOutput = AVCapturePhotoOutput()
    // 将captureSession改为类成员属性,保证生命周期
    private var captureSession: AVCaptureSession?

    public func initialize() {
        // 先检查相机权限
        switch AVCaptureDevice.authorizationStatus(for: .video) {
        case .authorized:
            setupCaptureSession()
        case .notDetermined:
            AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
                if granted {
                    DispatchQueue.main.async {
                        self?.setupCaptureSession()
                    }
                } else {
                    print("用户拒绝了相机权限")
                }
            }
        case .denied, .restricted:
            print("相机权限被拒绝或受限")
        @unknown default:
            print("未知的权限状态")
        }
    }

    private func setupCaptureSession() {
        let session = AVCaptureSession()
        session.sessionPreset = .photo // 设置会话预设为照片模式,适合拍照

        guard let captureDevice = AVCaptureDevice.default(for: .video) else {
            print("无法获取相机设备")
            return
        }

        do {
            let input = try AVCaptureDeviceInput(device: captureDevice)
            if session.canAddInput(input) {
                session.addInput(input)
            }
        } catch let error {
            print("设置输入设备失败: \(error)")
            return
        }

        if session.canAddOutput(photoOutput) {
            session.addOutput(photoOutput)
            // 配置照片输出的JPEG格式
            let photoSettings = AVCapturePhotoSettings(format: [AVVideoCodecKey: AVVideoCodecType.jpeg])
            photoOutput.setPreparedPhotoSettingsArray([photoSettings], completionHandler: nil)
        } else {
            print("无法添加输出设备")
            return
        }

        // 后台队列启动会话,避免阻塞主线程
        DispatchQueue.global(qos: .userInitiated).async {
            session.startRunning()
            self.captureSession = session
        }
    }

    public func takePhoto() {
        guard let session = captureSession, session.isRunning else {
            print("捕获会话未运行")
            return
        }

        let photoSettings = AVCapturePhotoSettings()
        if let photoPreviewType = photoSettings.availablePreviewPhotoPixelFormatTypes.first {
            photoSettings.previewPhotoFormat = [kCVPixelBufferPixelFormatTypeKey as String: photoPreviewType]
            photoOutput.capturePhoto(with: photoSettings, delegate: self)
        }
    }

    func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
        if let error = error {
            print("处理照片失败: \(error)")
            return
        }

        guard let imageData = photo.fileDataRepresentation(), let previewImage = UIImage(data: imageData) else {
            print("无法获取照片数据")
            return
        }

        // 后续处理或保存照片
        print("成功获取照片")
    }
}

额外说明

  • 调整方法名为小写开头(initialize、takePhoto),符合Swift命名规范。
  • 启动会话放在后台队列,避免主线程卡顿。
  • 补充完整的权限状态处理,确保只有获得权限后才初始化会话。

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 05:35:10