如何解决如何在SwiftUI应用中保存和加载ARWorldMap?
我遵循了YouTube教程,其中介绍了如何在SwiftUI中放置虚拟模型。
现在我可以放置模型了,我想保存和加载模型位置。
我已经制作了2个用于保存和加载的按钮,但是我不知道正确的代码来保存和加载实体和锚点。
以下代码位于我的updateUIView函数内部:
func updateUIView(_ uiView: ARView,context: Context) {
if let name = self.modelName {
print("Modell mit dem Namen \(name) wurde zum plaziert")
let filename = name + ".usdz"
let modelEntity = try! ModelEntity.loadModel(named: filename)
modelEntity.generateCollisionShapes(recursive: true)
uiView.installGestures(.all,for: modelEntity)
let anchorEntity = AnchorEntity(plane: .any)
anchorEntity.addChild(modelEntity)
uiView.scene.addAnchor(anchorEntity)
}
}
我尝试了一个“ else”语句,因为我一开始就有“ if”。但这没有解决。我做了一个状态变量(布尔型),当我按下保存或加载按钮时触发。但我无法正确连接到updateUIView-function。
更新1:
我在“ updateUIView”函数中实现了保存和加载函数,如下所示:
struct ARViewContainer: UIViewRepresentable {
@Binding var reset: Bool
@Binding var modelSelector: String
@Binding var save: Bool
@Binding var load: Bool
let config = ARWorldTrackingConfiguration()
func makeUIView(context: Context) -> ARView {
// create config for all entities
let arView = ARView(frame: .zero)
config.planeDetection = [.horizontal,.vertical]
config.environmentTexturing = .automatic
config.sceneReconstruction = .mesh
arView.session.run(config)
return arView
}
// App kontinuierlich beobachten
func updateUIView(_ uiView: ARView,context: Context) {
// create anchor and model-Entity
if modelSelector != "default" {
let modelEntity = try! ModelEntity.loadModel(named: "\(modelSelector)")
modelEntity.name = ("\(modelSelector)")
modelEntity.generateCollisionShapes(recursive: true)
uiView.installGestures(.all,for: modelEntity)
let anchor = AnchorEntity(plane: .any)
anchor.addChild(modelEntity)
uiView.scene.addAnchor(anchor)
}
// reset anchor
if reset == true {
uiView.scene.anchors.removeAll()
}
//MARK: saveload
if save == true {
uiView.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()
}
}
}
if load == true {
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
uiView.session.run(config)
}
}
}
//MARK:
}
}
通过直接将代码编写到updateUIView函数中,我可以使用uiView代替arView。只有config常量必须在makrUIView函数之外。 当我按下相应的按钮时,用于加载和保存的布尔值设置为false,但将为true:
struct SaveLoadReset: View {
@Binding var reset: Bool
@Binding var save: Bool
@Binding var load: Bool
@Binding var modelSelector: String
var body: some View {
//HStack für den Laden und Speichern Knopf
HStack(spacing: 10){
//save-Button:
Button(action: {
print("DEBUG: saveButton")
self.modelSelector = "default"
self.save = true
print("DEBUG: save = \(self.save)")
})
{
Image(systemName: "square.and.arrow.up")
.padding(20)
.background(Color.white)
.opacity(0.3)
.cornerRadius(20)
.padding(10)
.font(.title)
}
//load-Button:
Button(action: {
print("DEBUG: loadButton")
self.load = true
print("DEBUG: load = \(self.load)")
})
{
Image(systemName: "square.and.arrow.down")
.padding(20)
.background(Color.white)
.opacity(0.3)
.cornerRadius(20)
.font(.title)
}
Spacer()
//reset-Button:
Button(action: {
print("DEBUG: removeButton")
self.reset = true
print("DEBUG: reset = \(self.reset)" )
})
{
Image(systemName: "arrow.clockwise.circle")
.padding(20)
.background(Color.white)
.opacity(0.3)
.cornerRadius(20)
.font(.title)
.padding(10)
}
}
}
}
到目前为止,我还没有收到任何错误消息,但是我的代码似乎无法正常工作。 我可以按按钮,但是重新启动应用程序后,不会重新加载模型和锚点。
解决方法
您的代码可能如下所示:
import RealityKit
import SwiftUI
import ARKit
struct ARViewContainer: UIViewRepresentable {
@Binding var saved: Bool
@Binding var loaded: Bool
let anchor = AnchorEntity(world: [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()
方法的内容可能像这样:
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)
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。