【发布时间】:2021-01-09 17:04:34
【问题描述】:
我正在开发一个使用 ARkit 检测图像的应用。当检测到资产文件夹中的图像时,应用程序会在图像顶部显示一个 swiftUI 视图,当不再跟踪图像时,该 swiftUI 视图会消失。到这里为止一切正常。
在 viewController 文件中的 viewdidload 方法中,我正在从 Internet 下载并解析一个 csv 文件。这也有效。
我正在努力的地方是弄清楚如何将从 viewdidload 中的 csv 文件解析的数据传递到 swiftUI 视图,以便我可以在我正在创建的 swiftUI 视图上处理这些数据。例如,我将根据检测到的图像显示特定数据。
我发现了其他 stackoverflow 问题,他们讨论了如何在视图控制器之间传递数据,而不是在视图控制器和 swiftUI 视图之间传递数据。
下面是我的代码。
这是我的 ViewController.swift 文件
import UIKit
import SceneKit
import ARKit
import SwiftUI
class ViewController: UIViewController, ARSCNViewDelegate {
@IBOutlet var sceneView: ARSCNView!
override func viewDidLoad() {
super.viewDidLoad()
// Set the view's delegate
sceneView.delegate = self
// load csv file from dropbox
let url = URL(string: "https://www.dropbox.com/s/0d0cr5o9rfxzrva/test.csv?dl=1")!
let task = URLSession.shared.downloadTask(with: url) { location, response, error in
guard let location = location else { return }
do {
// get path to directory
let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
print(documentDirectory.path)
// giving name to file
let name = (response as? HTTPURLResponse)?.suggestedFilename ?? location.lastPathComponent
//create a destination url
let destination = documentDirectory.appendingPathComponent(name)
// check if file already exist
if FileManager.default.fileExists(atPath: destination.path) {
//remove the file
try FileManager.default.removeItem(at: destination)
}
// move file from old to new url
try FileManager.default.moveItem(at: location, to: destination)
// reading the file
let data = try String(contentsOf: destination, encoding: .utf8)
//parsed csv
let datos = self.csv(data: data)
print(datos)
} catch {
print("ERROR", error)
}
}
task.resume()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Create a session configuration
let configuration = ARImageTrackingConfiguration()
guard let trackingImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: nil) else {
fatalError("Couldn't load tracking images")
}
configuration.trackingImages = trackingImages
configuration.maximumNumberOfTrackedImages = 2
// Run the view's session
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// Pause the view's session
sceneView.session.pause()
}
// MARK: - ARSCNViewDelegate
// Override to create and configure nodes for anchors added to the view's session.
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
guard let imageAnchor = anchor as? ARImageAnchor else {return nil}
let plane = SCNPlane(width: imageAnchor.referenceImage.physicalSize.width,
height: imageAnchor.referenceImage.physicalSize.height)
let planeNode = SCNNode(geometry: plane)
planeNode.eulerAngles.x = -.pi / 2
if let imageName = imageAnchor.referenceImage.name {
imageController(for: planeNode, imageName: imageName)
}
let node = SCNNode()
node.addChildNode(planeNode)
return node
}
func imageController(for node: SCNNode, imageName: String) {
let imgView = UIHostingController(rootView: imageView(imageName: imageName))
DispatchQueue.main.async {
imgView.willMove(toParent: self)
self.addChild(imgView)
imgView.view.frame = CGRect(x: 0, y: 0, width: 500, height: 500)
self.view.addSubview(imgView.view)
self.showImageView(hostingVC: imgView, on: node)
}
}
func showImageView(hostingVC: UIHostingController<imageView>, on node: SCNNode) {
let material = SCNMaterial()
hostingVC.view.isOpaque = false
material.diffuse.contents = hostingVC.view
node.geometry?.materials = [material]
hostingVC.view.backgroundColor = UIColor.clear
}
// parsing csv method
func csv(data: String) -> [[String]] {
var result: [[String]] = []
let rows = data.components(separatedBy: "\n")
for row in rows {
let columns = row.components(separatedBy: ",")
result.append(columns)
}
return result
}
}
这是我的 swiftUI 视图文件
import SwiftUI
struct imageView: View {
var imageName: String
var body: some View {
ZStack{
Color.white
Text("hello \(imageName)")
}
}
}
【问题讨论】:
-
也许您可以尝试使用 NotificationCenter 或 Combine Publishers 来传递数据
-
您已经使用
imageName在控制器之间传递数据。只需添加另一个您想要发送到您的imageView类型的var,添加相同的var并键入您的ViewController。当您下载 csv 时,不要使用let davos创建变量,而是设置您刚刚在控制器上添加的属性,然后将var发送到您的imageView,就像发送imageName一样。 -
感谢@clawesome。我是这么想的,因为我可以通过 imageName。但是,当我尝试对
datos执行相同操作时,我得到“使用未解析的标识符”。我显然错过了一些东西。你能在我的代码上显示吗?谢谢。 -
datos是什么类类型? -
多维数组[[String]]
标签: ios swift swiftui viewcontroller arkit