我正在开发一个使用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)")
}
}
}
答案 0 :(得分:1)
您希望将datos
传递给View的构造函数,但是代码中唯一的datos
是闭包中的局部变量。
您需要在VC中创建一个新属性
var datos: [[String]]?
然后,当您获取数据时,将其保存在此属性中
self.datos = ....
然后,在构造视图时,传递self.datos