如何通过点击RealityKit中的实体打开SwiftUI视图?
方案一:使用NavigationLink实现导航
要在点击RealityKit实体后触发SwiftUI的NavigationLink导航,核心是通过绑定变量将AR视图中的点击事件传递到SwiftUI的视图层级中,具体修改步骤如下:
- 修改ARViewContainer.swift
- 给
Coordinator类添加绑定属性,用于触发导航状态变化 - 在
ARViewContainer结构体中添加@Binding变量,关联SwiftUI的状态 - 在点击实体的回调中设置绑定变量为
true,触发导航
- 给
修改后的代码:
class Coordinator: NSObject { weak var view: ARView? var shouldNavigate: Binding<Bool> // 新增绑定属性 init(shouldNavigate: Binding<Bool>) { self.shouldNavigate = shouldNavigate super.init() } @objc func handleTap(_ recognizer: UITapGestureRecognizer) { guard let view = self.view else { return } let tapLocation = recognizer.location(in: view) if let entity = view.entity(at: tapLocation) as? ModelEntity { print(entity.name) shouldNavigate.wrappedValue = true // 触发导航状态 } } } struct ARViewContainer: UIViewRepresentable { typealias UIViewType = ARView @Binding var shouldNavigate: Bool // 新增绑定变量 func makeUIView(context: Context) -> ARView{ let arView = ARView(frame: .zero, cameraMode: .ar, automaticallyConfigureSession: true) context.coordinator.view = arView arView.addGestureRecognizer(UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap))) arView.scene.anchors.removeAll() let anchor = AnchorEntity() let plane = MeshResource.generatePlane(width: 1, height: 1) var material = UnlitMaterial() material.color = .init(tint: .white, texture: .init(try! .load(named: "instagram"))) let planeEntity = ModelEntity(mesh: plane, materials: [material]) planeEntity.generateCollisionShapes(recursive: true) planeEntity.name = "Plane Entity" planeEntity.position.z -= 1.0 planeEntity.setParent(anchor) arView.scene.addAnchor(anchor) return arView } func updateUIView(_ uiView: ARView, context: Context){} func makeCoordinator() -> Coordinator { Coordinator(shouldNavigate: $shouldNavigate) // 初始化协调器时传入绑定 } }
- 修改ContentView.swift
- 添加
@State变量管理导航状态 - 加入绑定到该状态的
NavigationLink(用EmptyView作为占位,避免影响AR视图显示)
- 添加
修改后的代码:
struct ContentView: View { @State private var shouldNavigate = false var body: some View { NavigationView{ ZStack { ARViewContainer(shouldNavigate: $shouldNavigate) .ignoresSafeArea(.all) // 绑定状态的NavigationLink,占位视图不影响界面 NavigationLink( destination: TestView(), isActive: $shouldNavigate, label: { EmptyView() } ) } } } }
方案二:使用fullScreenCover实现全屏跳转
如果NavigationLink不符合需求,可改用fullScreenCover,只需修改ContentView.swift的代码即可(ARViewContainer的修改和方案一一致):
修改后的ContentView:
struct ContentView: View { @State private var shouldNavigate = false var body: some View { ZStack { ARViewContainer(shouldNavigate: $shouldNavigate) .ignoresSafeArea(.all) } .fullScreenCover(isPresented: $shouldNavigate) { TestView() } } }
核心原理说明
- 通过
@Binding在UIKit(ARView)和SwiftUI视图之间建立状态传递通道,让AR视图中的点击事件能触发SwiftUI的导航逻辑 - 两种方案都无需修改
TestView的代码,保持原有结构即可
内容的提问来源于stack exchange,提问作者Milly Alfaro
相关产品推荐
相关产品推荐

