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

自定义QLPreviewController的ARQuickLook切换USDZ模型异常问题求解

问题根因

你遇到的问题本质是QLPreviewController不支持子类化修改视图层级、也不支持热重载当前预览的USDZ模型,调用reloadData/refreshCurrentPreviewItem会强制中断内部AR会话,切回物体预览模式,甚至出现会话泄露导致后续AR功能失效。

可行解决方案

方案1:使用RealityKit的ARView自主实现AR预览(最稳定)

苹果官方不推荐子类化QLPreviewController,如果需要自定义AR预览页的UI和交互,直接用ARView加载USDZ是最优解,全程AR会话不会中断,完全可控:

  • 新建普通UIViewController,视图层级最底层放ARView作为USDZ渲染载体,上层直接叠加你需要的collectionView、按钮等自定义UI,无需修改任何系统组件的视图结构
  • 切换商品颜色时直接替换ARView场景内的模型即可,无需重启AR会话
    示例代码如下:
import RealityKit
import ARKit

class CustomARViewController: UIViewController {
    let arView = ARView(frame: .zero)
    var currentModelEntity: Entity?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 配置AR基础能力
        arView.frame = view.bounds
        arView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(arView)
        // 开启原生QuickLook同款的模型自动放置、缩放/旋转/平移手势
        arView.automaticallyConfigureSession = true
        arView.installGestures([.rotation, .scale, .translation], for: nil)
        // 添加自定义UI组件
        setupCustomUIElements()
        // 加载默认颜色的USDZ模型
        loadUSDZModel(url: getDefaultProductUrl())
    }
    
    private func loadUSDZModel(url: URL) {
        // 移除旧模型
        currentModelEntity?.removeFromParent()
        do {
            // 加载新USDZ模型并添加到场景
            let newModel = try Entity.load(contentsOf: url)
            let anchor = AnchorEntity(plane: .horizontal)
            anchor.addChild(newModel)
            arView.scene.addAnchor(anchor)
            currentModelEntity = newModel
        } catch {
            print("USDZ模型加载失败:\(error.localizedDescription)")
        }
    }
    
    // collectionView选中颜色时调用
    func didSelectColor(at index: Int) {
        let targetModelUrl = getProductUrl(colorIndex: index)
        loadUSDZModel(url: targetModelUrl)
    }
}

方案2:必须保留QLPreviewController的适配方案

如果一定要用QLPreviewController的原生能力,按如下方式修改即可解决90%以上的异常:

  • 不要子类化QLPreviewController添加自定义视图,而是把你的collectionView、按钮等UI加到当前的keyWindow或者QLPreviewController的presentingViewController的view上,避免修改系统组件的视图层级
  • 不要调用reloadData/refreshCurrentPreviewItem重载模型,提前把所有颜色对应的USDZ URL预存到数组中,让numberOfPreviewItems返回数组的总长度
  • 用户切换颜色时,直接调用setCurrentPreviewItemIndex(_:animated:)方法切换到对应索引的预览项即可
    注意:该方案在部分旧iOS版本上仍可能出现AR会话中断的问题,兼容性不如方案1
额外注意事项
  • 所有USDZ文件要提前下载到本地沙盒再传入预览组件,不要直接加载远程URL
  • AR会话异常时可以调用ARSession.shared().reset()手动重置,避免必须重启APP才能恢复的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 04:15:02