如何用枚举实现相机输入切换开关?编译报错求解
解决Camera切换时枚举方法访问实例变量的编译错误
你遇到的这个编译错误,核心问题是CameraPosition枚举的toggle()方法没办法直接访问Camera类里的实例成员(比如currentCameraInput)。枚举的实例方法默认只能访问枚举自身的属性和方法,它不知道你要操作的是哪个Camera实例,所以编译器会误以为你想访问Camera类的静态成员,自然就报错了。另外还要注意,你原来的toggle()方法逻辑其实没实现真正的“切换”——比如当前是.front时,它还是把currentCameraInput设为前置输入,并没有切换到后置,这也是需要修正的点。
下面给你两种可行的修复方案:
方案一:让枚举只负责表示位置,把切换逻辑移到Camera类中
这种方式更符合单一职责原则,枚举仅定义相机位置的枚举值,实际的输入切换逻辑放在Camera类的方法里,结构更清晰:
class Camera { // 给当前相机位置设置默认值(默认后置相机更合理) var currentCameraPosition: CameraPosition = .rear var frontCameraInput: AVCaptureDeviceInput? var rearCameraInput: AVCaptureDeviceInput? var currentCameraInput: AVCaptureDeviceInput? // 假设你有一个AVCaptureSession实例 private var captureSession: AVCaptureSession? enum CameraPosition { case front case rear // 枚举只负责返回切换后的位置 func toggled() -> CameraPosition { switch self { case .front: return .rear case .rear: return .front } } } // 在Camera类里实现完整的切换逻辑 func toggleCamera() { // 切换当前相机位置 currentCameraPosition = currentCameraPosition.toggled() // 赋值对应的相机输入 currentCameraInput = currentCameraPosition == .front ? frontCameraInput : rearCameraInput // 关键:更新AVCaptureSession的输入(必须在配置块内操作) guard let session = captureSession, let newInput = currentCameraInput else { return } session.beginConfiguration() // 移除旧输入(如果有的话) if let oldInput = session.inputs.first { session.removeInput(oldInput) } // 添加新输入 if session.canAddInput(newInput) { session.addInput(newInput) } session.commitConfiguration() } }
方案二:让枚举方法接收Camera实例作为参数
如果你坚持要在枚举方法里处理切换逻辑,可以让toggle方法接收Camera类的实例作为参数,这样就能通过实例访问到对应的成员变量了:
class Camera { var currentCameraPosition: CameraPosition = .rear var frontCameraInput: AVCaptureDeviceInput? var rearCameraInput: AVCaptureDeviceInput? var currentCameraInput: AVCaptureDeviceInput? private var captureSession: AVCaptureSession? enum CameraPosition { case front case rear func toggle(for camera: Camera) { // 先计算切换后的位置 let newPosition: CameraPosition = self == .front ? .rear : .front // 更新Camera实例的位置和输入 camera.currentCameraPosition = newPosition camera.currentCameraInput = newPosition == .front ? camera.frontCameraInput : camera.rearCameraInput // 同样需要更新会话输入 guard let session = camera.captureSession, let newInput = camera.currentCameraInput else { return } session.beginConfiguration() if let oldInput = session.inputs.first { session.removeInput(oldInput) } if session.canAddInput(newInput) { session.addInput(newInput) } session.commitConfiguration() } } } // 使用示例 let camera = Camera() camera.currentCameraPosition.toggle(for: camera)
重要提醒
不管用哪种方案,修改AVCaptureSession的输入时,必须包裹在beginConfiguration()和commitConfiguration()之间,这是因为会话的配置变更必须原子性地完成,否则会导致线程问题或者配置失效。另外,一定要通过canAddInput判断输入是否可添加,避免因设备不可用等情况导致崩溃。
内容的提问来源于stack exchange,提问作者dre_84w934
相关产品推荐
相关产品推荐

