Swift开发iOS相机应用前后置相机切换异常问题求助
修复iOS相机前后置切换失效的问题
嘿,我仔细看了你的代码,发现几个关键问题导致切换相机功能失效,咱们一步步来修复:
核心问题分析
- 重复创建CaptureSession且未清理旧资源:你每次切换相机时都重新初始化了
captureSession,还直接把新的videoPreviewLayer叠加到ImageView上,这会导致旧的会话和图层残留,新会话无法正常接管相机资源。 - 相机设备获取兼容性差:使用
.builtInDualCamera只能获取双摄像头设备的相机,单摄设备(比如iPhone SE 第一代)会返回nil,应该用.builtInWideAngleCamera来兼容所有带摄像头的iOS设备。 - Session配置顺序错误:在
viewDidLoad中,你先启动了session,之后才添加AVCapturePhotoOutput和设置sessionPreset,这些配置需要在session启动前完成才能生效。
修复后的完整代码
import UIKit import AVFoundation class ViewController: UIViewController { @IBOutlet weak var imageView: UIView! // 变量名改用小驼峰,符合Swift规范 var captureSession: AVCaptureSession? var videoPreviewLayer: AVCaptureVideoPreviewLayer? var capturePhotoOutput: AVCapturePhotoOutput? override func viewDidLoad() { super.viewDidLoad() setupCamera(with: .back) // 初始化时直接调用通用设置函数 } // 通用相机设置函数,传入要切换的相机位置 private func setupCamera(with position: AVCaptureDevice.Position) { // 停止当前会话(如果存在) captureSession?.stopRunning() // 1. 获取指定位置的相机设备 guard let captureDevice = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: position) else { print("无法获取指定位置的相机") return } // 2. 配置Session let session = AVCaptureSession() session.sessionPreset = .photo // 先设置预设 do { // 添加视频输入 let input = try AVCaptureDeviceInput(device: captureDevice) if session.canAddInput(input) { session.addInput(input) } // 添加拍照输出 let photoOutput = AVCapturePhotoOutput() photoOutput.isHighResolutionCaptureEnabled = true photoOutput.isDepthDataDeliveryEnabled = photoOutput.isDepthDataDeliverySupported photoOutput.isPortraitEffectsMatteDeliveryEnabled = photoOutput.isPortraitEffectsMatteDeliverySupported if session.canAddOutput(photoOutput) { session.addOutput(photoOutput) capturePhotoOutput = photoOutput } // 3. 配置预览层 let previewLayer = AVCaptureVideoPreviewLayer(session: session) previewLayer.frame = imageView.layer.bounds previewLayer.videoGravity = .resizeAspectFill // 添加视频填充模式,避免拉伸 // 移除旧的预览层,添加新的 imageView.layer.sublayers?.forEach { $0.removeFromSuperlayer() } imageView.layer.addSublayer(previewLayer) // 保存会话和预览层的引用 captureSession = session videoPreviewLayer = previewLayer // 4. 启动会话 session.startRunning() } catch { print("相机配置错误: \(error.localizedDescription)") } } @IBAction func rotateCamera(_ sender: Any) { guard let currentInput = captureSession?.inputs.first as? AVCaptureDeviceInput else { print("无法获取当前相机输入") return } // 根据当前相机位置切换到相反的相机 let targetPosition: AVCaptureDevice.Position = currentInput.device.position == .back ? .front : .back setupCamera(with: targetPosition) } }
关键修复点说明
- 复用+清理资源:每次切换时先停止旧会话,移除旧的预览层,避免资源冲突和图层叠加。
- 通用相机获取:用
.builtInWideAngleCamera替代.builtInDualCamera,兼容更多设备。 - 统一配置流程:把相机配置逻辑封装到一个函数中,确保预设、输入输出添加都在会话启动前完成。
- 规范命名:把
ImageView改成imageView,符合Swift的命名规范,避免和系统类混淆。
现在你可以测试一下,切换按钮应该能正常在前后置相机之间切换了!
内容的提问来源于stack exchange,提问作者UIB
相关产品推荐
相关产品推荐

