SwiftUI中如何实现自定义CameraView的显示与隐藏切换
实现CameraView的显示/隐藏切换逻辑
1. 在updateUIView里处理状态同步
updateUIView是SwiftUI同步状态到UIKit视图的核心方法,你直接在这里根据showCameraView的绑定值控制相机显隐,同时必须管理AVCaptureSession的生命周期——相机属于高资源组件,不用时及时停止会话,避免后台占用系统资源。
核心逻辑很明确:
- 当
showCameraView变为true:显示相机视图,启动捕获会话,先检查相机权限(没授权就请求) - 当
showCameraView变为false:隐藏相机视图,停止捕获会话,释放预览层等资源
给你完整的CameraView实现代码,直接用就行:
import SwiftUI import AVFoundation struct CameraView: UIViewRepresentable { @Binding var showCameraView: Bool // 自定义UIView子类,负责承载相机预览 class CameraViewfinder: UIView { private var captureSession: AVCaptureSession? private var previewLayer: AVCaptureVideoPreviewLayer? // 启动相机会话 func startCamera() { guard captureSession == nil else { return } let session = AVCaptureSession() session.sessionPreset = .photo // 配置后置摄像头输入 guard let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else { return } do { let input = try AVCaptureDeviceInput(device: device) if session.canAddInput(input) { session.addInput(input) // 创建预览层并添加到视图 let previewLayer = AVCaptureVideoPreviewLayer(session: session) previewLayer.frame = bounds previewLayer.videoGravity = .resizeAspectFill layer.addSublayer(previewLayer) self.previewLayer = previewLayer // 异步启动会话,避免阻塞主线程 DispatchQueue.global(qos: .userInitiated).async { session.startRunning() self.captureSession = session } } } catch { print("相机配置失败: \(error.localizedDescription)") } } // 停止相机会话并清理资源 func stopCamera() { captureSession?.stopRunning() captureSession = nil previewLayer?.removeFromSuperlayer() previewLayer = nil } } // 创建UIView实例 func makeUIView(context: Context) -> CameraViewfinder { let view = CameraViewfinder() view.isHidden = !showCameraView if showCameraView { view.startCamera() } return view } // 更新UIView状态 func updateUIView(_ uiView: CameraViewfinder, context: Context) { // 只在状态变化时执行操作,避免重复调用 if showCameraView != !uiView.isHidden { uiView.isHidden = !showCameraView if showCameraView { // 处理相机权限 switch AVCaptureDevice.authorizationStatus(for: .video) { case .authorized: uiView.startCamera() case .notDetermined: AVCaptureDevice.requestAccess(for: .video) { granted in DispatchQueue.main.async { if granted { uiView.startCamera() } else { // 权限被拒,自动关闭相机视图 self.showCameraView = false } } } default: // 权限受限或被拒,直接关闭相机视图 self.showCameraView = false } } else { uiView.stopCamera() } } } }
2. SwiftUI调用示例
按照你期望的方式使用,我加了过渡动画和点击关闭的逻辑,更贴近社交APP的体验:
struct ContentView: View { @State var showCamera: Bool = false var body: some View { // 你的主Tab视图 TabView { Text("主页") .tabItem { Image(systemName: "house") } Text("发现") .tabItem { Image(systemName: "magnifyingglass") } } .overlay(alignment: .center) { // 仅当showCamera为true时显示相机视图 if showCamera { CameraView(showCameraView: $showCamera) .ignoresSafeArea() .transition(.opacity) // 添加淡入淡出过渡 .onTapGesture { showCamera = false // 点击相机区域关闭 } } } .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button(action: { showCamera = true }) { Image(systemName: "camera") } } } } }
3. 同类场景学习资源
- Apple官方文档:重点啃
UIViewRepresentable协议说明,以及AVCaptureSession的生命周期管理,搞懂SwiftUI和UIKit的交互逻辑 - 苹果Sample Code:搜"AVFoundation Camera"相关示例,学习相机权限请求、会话管理的最佳实践
- SwiftUI官方教程:看"Integrating SwiftUI with UIKit"章节,掌握跨框架视图通信的核心方法
内容的提问来源于stack exchange,提问作者Apekshik Panigrahi
相关产品推荐
相关产品推荐

