Swift 4中相机预览层无法在指定小UIView显示的问题求助
解决相机预览层无法显示在小UIView上的问题
我来帮你搞定这个问题!你遇到的情况其实很常见,核心问题大概率是预览层的frame设置时机不对,或者小UIView(mirrorView)的布局还没完成导致的。咱们一步步来排查和解决:
问题根源分析
你传入self.view时能正常显示,是因为self.view在viewDidLoad阶段就已经有了确定的frame;但你的mirrorView如果用了Auto Layout布局,在configureCameraController调用时,它的frame可能还是初始的占位值(比如CGRectZero或者storyboard里的临时尺寸),这时候给previewLayer设置错误的frame,自然就看不到预览了。
解决方案
1. 修正预览层的frame设置逻辑
把预览层的frame从view.frame改成view.bounds(bounds是视图自身的坐标系统,更适合图层布局),同时添加监听来适配视图尺寸变化:
func displayPreview(on view: UIView) throws { guard let captureSession = self.captureSession, captureSession.isRunning else { throw CameraControllerError.captureSessionIsMissing } self.previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) self.previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill self.previewLayer?.connection?.videoOrientation = .portrait // 改用bounds而非frame,适配视图自身的尺寸 self.previewLayer?.frame = view.bounds view.layer.insertSublayer(self.previewLayer!, at: 0) // 监听视图bounds变化,自动更新预览层尺寸(适配旋转、布局调整) NotificationCenter.default.addObserver( self, selector: #selector(updatePreviewLayerFrame), name: UIView.boundsDidChangeNotification, object: view ) } @objc private func updatePreviewLayerFrame(notification: NSNotification) { guard let view = notification.object as? UIView, let previewLayer = self.previewLayer else { return } previewLayer.frame = view.bounds }
2. 调整预览层的初始化时机
不要在configureCameraController的异步回调里直接调用displayPreview,而是等到视图布局完成后再初始化预览层——比如在viewDidLayoutSubviews中执行:
override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // 避免重复添加图层,只初始化一次 guard cameraController.previewLayer == nil else { return } do { try cameraController.displayPreview(on: self.mirrorView) } catch { print("预览初始化失败:\(error)") } }
3. 额外检查项
- 确保
mirrorView的clipsToBounds属性设为true,这样预览层超出视图范围的部分会被裁剪,显示更规整; - 可以给
mirrorView设置一个临时的背景色(比如灰色),确认视图本身已经正确布局在屏幕上,排除视图未显示的问题; - 记得在控制器销毁时移除通知监听,避免内存泄漏:
deinit { NotificationCenter.default.removeObserver(self) }
调整后的configureCameraController
只保留相机初始化逻辑,把预览层的创建交给布局回调:
func configureCameraController() { cameraController.prepare { error in if let error = error { print("相机初始化错误:\(error)") } print("相机准备完成") } }
内容的提问来源于stack exchange,提问作者coder
相关产品推荐
相关产品推荐

