Swift/SwiftUI中AVFoundation相机经NavigationLink跳转返回后配置失败问题
故障根因
该报错触发的核心原因是:CameraView的onAppear回调会在每次页面从导航栈返回前台时触发,你在其中每次都调用了model.configure()执行相机配置逻辑。而通过NavigationLink跳转新页面时,底层的CameraView实例和对应的AVCaptureSession对象并没有被销毁,session里已经挂载了之前添加的视频输入设备,第二次执行配置时重复尝试添加输入源就会触发canAddInput校验失败。
修复方案
1. 配置前先清理session已有资源
首先修改CameraService的configure方法,每次执行配置前先清空session已挂载的输入、输出,避免重复添加冲突:
func configure() { session.beginConfiguration() // 清理已有输入 session.inputs.forEach { session.removeInput($0) } // 清理已有输出 session.outputs.forEach { session.removeOutput($0) } // 此处保留你原有配置逻辑 let videoDeviceInput = try AVCaptureDeviceInput(device: videoDevice) if session.canAddInput(videoDeviceInput) { session.addInput(videoDeviceInput) self.videoDeviceInput = videoDeviceInput } else { print("Couldn't add video device input to the session.") setupResult = .configurationFailed session.commitConfiguration() return } // ... 其余原有配置代码 }
2. 增加配置完成标识避免重复初始化
给CameraModel新增配置状态标识,确保配置逻辑全局只执行一次,不需要每次页面显示都重复调用:
final class CameraModel: ObservableObject { private var hasConfigured = false // ... 其余原有属性 func configure() { guard !hasConfigured else { return } service.checkForPermissions() service.configure() hasConfigured = true } }
3. 可选:优化会话生命周期管理
如果需要支持页面切后台后停止相机、回到页面重启的逻辑,可以在CameraView中新增生命周期回调:
// CameraView的CameraPreview组件回调部分修改为 CameraPreview(session: model.session) .gesture(/* 原有手势逻辑 */) .onAppear { model.configure() // 会话未运行时重启,不需要重新配置 if !model.session.isRunning { DispatchQueue.global(qos: .userInitiated).async { model.session.startRunning() } } } .onDisappear { // 页面隐藏时停止会话节约资源 model.session.stopRunning() } // ... 其余原有修饰符
内容的提问来源于stack exchange,提问作者krish
相关产品推荐
相关产品推荐

