You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AVCaptureVideoPreviewLayer调整大小时生成两个视图的问题求助

解决AVCaptureVideoPreviewLayer调整视图大小时出现重复层的问题

看起来你遇到的问题大概率是重复调用了displayPreview(on:)方法——每次调用都会新建一个AVCaptureVideoPreviewLayer并插入到视图的layer中,次数多了就会叠加出多个预览层。另外,就算只调用一次,如果没同步更新预览层的frame,也可能因为视图尺寸变化导致视觉异常(不过你明确说出现两个视图,重复添加的可能性更高)。

下面给你几个针对性的解决方案:

方案1:复用已有预览层,避免重复创建

修改你的displayPreview(on:)方法,先检查是否已经存在previewLayer,有就直接更新它的布局和session,不用重新创建:

func displayPreview(on view: UIView) throws { 
    guard let captureSession = self.captureSession, captureSession.isRunning else { 
        throw CameraControllerError.captureSessionIsMissing 
    } 

    // 已有预览层则直接更新
    if let existingPreviewLayer = previewLayer {
        // 同步session(如果session有变更的话)
        if existingPreviewLayer.session != captureSession {
            existingPreviewLayer.session = captureSession
        }
        // 更新frame匹配当前视图大小
        existingPreviewLayer.frame = view.bounds
        // 确保预览层在最底层
        view.layer.insertSublayer(existingPreviewLayer, at: 0)
    } else {
        // 首次创建预览层
        previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        previewLayer?.frame = view.bounds
        // 设置视频填充模式,避免拉伸变形
        previewLayer?.videoGravity = .resizeAspectFill
        view.layer.insertSublayer(previewLayer!, at: 0)
    }
}

方案2:监听视图布局变化,同步更新预览层frame

在CameraViewController中重写viewDidLayoutSubviews,每次视图布局更新时主动调整预览层的frame:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    // 直接更新预览层的frame
    camera.previewLayer?.frame = self.view.bounds
}

方案3:控制displayPreview(on:)的调用次数

检查代码中是否在viewWillAppear、viewDidAppear或者视图尺寸变化的回调中重复调用了displayPreview(on:),确保只在初始化时调用一次,后续只更新frame即可。比如在viewDidLoad中调用:

override func viewDidLoad() {
    super.viewDidLoad()
    do {
        try camera.displayPreview(on: self.view)
    } catch {
        print("预览层设置失败:\(error)")
    }
}

额外提示:及时清理预览层

如果需要在视图销毁或相机停止时清理资源,可以给Camera对象添加清理方法:

func cleanupPreview() {
    previewLayer?.removeFromSuperlayer()
    previewLayer = nil
}

然后在CameraViewController的viewWillDisappear中调用:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    camera.cleanupPreview()
}

这样应该就能解决你遇到的调整视图大小时出现两个预览层的问题了。

内容的提问来源于stack exchange,提问作者dre_84w934

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:40:21