且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在SwiftUI应用中保存和加载ARWorldMap?

更新时间:2023-12-01 23:15:46

您的代码可能如下所示:

Your code might look like this:

import RealityKit
import SwiftUI
import ARKit

struct ARViewContainer: UIViewRepresentable {

    @Binding var saved: Bool
    @Binding var loaded: Bool
    
    let anchor = AnchorEntity(world: [0, 0,-2])
    let arView = ARView(frame: .zero)
    let config = ARWorldTrackingConfiguration()
    
    func makeUIView(context: Context) -> ARView {
        
        let sphere = MeshResource.generateSphere(radius: 1)
        let sphereEntity = ModelEntity(mesh: sphere)
        sphereEntity.name = "SPHERE"
        sphereEntity.setParent(anchor)
        arView.scene.anchors.append(anchor)
        return arView
    }        
    fileprivate func saveWorldMap() {
        print("SAVED")
        DispatchQueue.main.async {
            saved = false
        }
    }
    fileprivate func loadWorldMap() {
        print("LOADED")
        DispatchQueue.main.async {
            loaded = false
        }
    } 
   
    func updateUIView(_ uiView: ARView, context: Context) {
        
        // Retrieve the entity from your scene
        guard let entity = uiView.scene.findEntity(named: "SPHERE")
        else { return }
                        
        if saved {
            self.saveWorldMap()
        }
        if loaded {
            self.loadWorldMap()
        }
    }
}

struct ContentView : View {
    
    @State private var saver = false
    @State private var loader = false
    
    var body: some View {
        VStack {
            ARViewContainer(saved: $saver, loaded: $loader)
            HStack {
                Spacer()
                Button(action: { self.saver.toggle() }) {
                    Text("Save")
                }
                Spacer()
                Button(action: { self.loader.toggle() }) {
                    Text("Load")
                }
                Spacer()
            }
        }
    }
}

saveWorldMap()和 loadWorldMap()方法的内容可能是这样的:

The content of saveWorldMap() and loadWorldMap() methods might be like that:

fileprivate func saveWorldMap() {

    arView.session.getCurrentWorldMap { (worldMap, _) in
        
        if let map: ARWorldMap = worldMap {
            
            let data = try! NSKeyedArchiver.archivedData(withRootObject: map, 
                                                  requiringSecureCoding: true)
            
            let savedMap = UserDefaults.standard
            savedMap.set(data, forKey: "WorldMap")
            savedMap.synchronize()
        }
    }
}

fileprivate func loadWorldMap() {

    let storedData = UserDefaults.standard

    if let data = storedData.data(forKey: "WorldMap") {

        if let unarchiver = try? NSKeyedUnarchiver.unarchivedObject(
                               ofClasses: [ARWorldMap.classForKeyedUnarchiver()],
                                    from: data),
           let worldMap = unarchiver as? ARWorldMap {

                config.initialWorldMap = worldMap
                arView.session.run(config)
        }
    }
}