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

SwiftUI中如何实现暂停AR会话并清理变量与锚点的功能?

解决方案

我们可以通过绑定状态传递信号+引用类型协调器管理AR资源的方式实现暂停AR会话、清理字典和移除锚点的功能,以下是具体修改步骤和代码:

1. 重构ARExperience结构体

将AR视图、实体字典移到Coordinator(引用类型)中,避免值类型结构体的副本问题,同时添加绑定变量和清理函数:

struct ARExperience: UIViewRepresentable {
    // 绑定主视图的停止信号
    @Binding var shouldStopAR: Bool
    
    func makeCoordinator() -> Coordinator {
        Coordinator()
    }
    
    class Coordinator: NSObject, ARSessionDelegate {
        var arView: ARView!
        // 移到协调器中,确保修改实时生效
        var entityDictionaries = [String: (anchor: AnchorEntity, model: ModelEntity)]()
        
        func session(_ session: ARSession, didAdd anchors: [ARAnchor]) {
            guard let validAnchor = anchors[0] as? ARImageAnchor else { return }
            let anchor = AnchorEntity(anchor: validAnchor)
            let videoPlane = createdVideoPlayerNodeFor(validAnchor.referenceImage)
            anchor.addChild(videoPlane)
            arView.scene.addAnchor(anchor)
            if let targetName = validAnchor.referenceImage.name {
                entityDictionaries[targetName] = (anchor, videoPlane)
            }
        }

        func session(_ session: ARSession, didUpdate anchors: [ARAnchor]) {
            // 保留你的更新逻辑
        }
        
        // 核心清理函数
        func cleanupARSession() {
            // 1. 暂停AR会话
            arView.session.pause()
            
            // 2. 从场景中移除所有锚点实体
            for (_, value) in entityDictionaries {
                arView.scene.removeAnchor(value.anchor)
                // 可选:停止视频播放,释放资源
                // (如果你的videoPlane包含AVPlayer,这里需要调用player.pause())
            }
            
            // 3. 清空实体字典
            entityDictionaries.removeAll()
            
            // 可选:彻底移除AR会话中的原生锚点
            arView.session.currentFrame?.anchors.forEach { anchor in
                arView.session.remove(anchor: anchor)
            }
        }
    }

    func makeUIView(context: Context) -> ARView {
        let arView = ARView(frame: .zero)
        context.coordinator.arView = arView
        arView.session.delegate = context.coordinator
        // 在这里配置你的AR会话(比如ARImageTrackingConfiguration)
        return arView
    }
    
    func updateUIView(_ uiView: ARView, context: Context) {
        // 监听停止信号,触发清理
        if shouldStopAR {
            context.coordinator.cleanupARSession()
            // 重置信号,避免重复触发
            shouldStopAR = false
        }
    }
    
    // 保留你的视频节点创建函数
    private func createdVideoPlayerNodeFor(_ referenceImage: ARReferenceImage) -> ModelEntity {
        let plane = ModelEntity(mesh: .generatePlane(width: referenceImage.physicalSize.width, height: referenceImage.physicalSize.height))
        // 补充你的视频播放器配置逻辑
        return plane
    }
}

2. 修改主视图InitiateARView

添加状态变量绑定到ARExperience,点击按钮时触发停止信号:

struct InitiateARView: View {
    @StateObject var vm = ARPreparationViewModel()
    // 管理AR停止状态
    @State private var shouldStopAR = false
    
    var body: some View {
        VStack {
             if vm.isLoading {
                 Button("Start", action: {
                     vm.prepareAR()
                 })
             } else {
                 ZStack {
                     // 传递绑定状态
                     ARExperience(shouldStopAR: $shouldStopAR)
                         .edgesIgnoringSafeArea(.all)
                     VStack {
                         HStack {
                             Spacer()
                             Button("Stop AR", action: {
                                // 触发停止信号
                                shouldStopAR = true
                             })
                         }
                         Spacer()
                     }
                 }
             }  
         }
     }
}

关键逻辑说明

  • 绑定状态传递:通过@Binding在主视图和ARExperience之间传递停止信号,实现跨组件的事件触发。
  • 引用类型协调器:将AR视图、实体字典放在Coordinator(类类型)中,避免结构体值传递导致的副本失效问题,确保修改实时生效。
  • 完整清理流程:暂停会话→移除场景锚点→清空字典→可选移除原生锚点,确保AR资源被彻底释放。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 06:15:13