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

SwiftUI异步加载Reality Composer场景并绑定ARViewContainer后如何触发通知?

问题:异步加载Reality Composer场景后无法触发通知

我希望在Reality Composer场景中使用Scene1.notifications.replay.post()这类通知功能,于是在SwiftUI的ContentView中异步加载场景并绑定到ARViewContainer添加场景,但操作无效,原代码如下:

struct ContentView: View {
    @State private var arView = ARView(frame: .zero)
    @State private var Scene1 = Experience.loadSceneAsync(completion: { result in
        do {
            let Scene = try result.get()
        } catch {
            print("Error")
        }
    })

    var body: some View {
       ZStack {
         ARViewContainer(arView: $arView, Scene1: $Scene1)
           .ignoresSafeArea()
         Button("play") {
           Scene1.notifications.replay.post()
         }
       }
    }
}

struct ARViewContainer: UIViewRepresentable {
    @Binding var arView: ARView
    @Binding var Scene1: Experience1.Scene1

    func makeUIView(context: Context) -> ARView {
        
        arView.scene.anchors.append(Scene1)
     
        return ARView
    }
}

问题分析

  • loadSceneAsync是异步方法,返回值为Void,不能直接赋值给@State变量Scene1,原代码的异步回调未将加载后的场景实例保存到Scene1,导致后续调用通知时Scene1并非有效场景实例。
  • ARViewContainer的makeUIView错误返回了ARView类型而非实例arView,且异步加载可能未完成时Scene1为空,直接添加锚点会失败。
  • Scene1应定义为可选类型,适配异步加载未完成时的空状态。

修正后的代码

ContentView部分

struct ContentView: View {
    @State private var arView = ARView(frame: .zero)
    @State private var scene1: Experience1.Scene1? // 改为可选类型存储加载后的场景

    var body: some View {
        ZStack {
            ARViewContainer(arView: $arView, scene1: $scene1)
                .ignoresSafeArea()
            Button("play") {
                scene1?.notifications.replay.post() // 用可选链避免空值崩溃
            }
        }
        .onAppear {
            // 视图出现时启动异步加载
            Experience.loadScene1Async { result in
                do {
                    self.scene1 = try result.get()
                } catch {
                    print("加载场景失败:\(error.localizedDescription)")
                }
            }
        }
    }
}

ARViewContainer部分

struct ARViewContainer: UIViewRepresentable {
    @Binding var arView: ARView
    @Binding var scene1: Experience1.Scene1?

    func makeUIView(context: Context) -> ARView {
        return arView
    }

    func updateUIView(_ uiView: ARView, context: Context) {
        // 当scene1有值且未添加到锚点时,添加到ARView
        guard let scene = scene1, !uiView.scene.anchors.contains(scene) else { return }
        uiView.scene.anchors.append(scene)
    }
}

关键修改说明

  1. 将Scene1改为可选类型Experience1.Scene1?,适配异步加载未完成时的空状态。
  2. 在onAppear中触发异步加载,将结果赋值给scene1,确保视图出现后才开始加载场景。
  3. 把场景添加逻辑移到updateUIView方法中,该方法会在绑定的scene1变化时触发,保证场景加载完成后才添加到ARView锚点。
  4. 按钮触发通知时使用可选链scene1?.notifications.replay.post(),避免场景未加载完成导致的崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 12:17:25