使用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
相关产品推荐
相关产品推荐

