Wie übergebe ich Daten von viewController an swiftUI view?
Ich arbeite an einer App, die ARkit verwendet, um Bilder zu erkennen. Wenn ein Bild im Asset-Ordner erkannt wird, zeigt die App eine SwiftUI-Ansicht über dem Bild an. Wenn ein Bild nicht mehr verfolgt wird, verschwindet die SwiftUI-Ansicht. Bis hierher funktioniert alles gut.
Innerhalb der viewdidload-Methode in der viewController-Datei lade ich eine CSV-Datei aus dem Internet herunter und analysiere sie. Das funktioniert auch.
Ich habe Probleme damit, herauszufinden, wie die aus der CSV-Datei in viewdidload analysierten Daten an die swiftUI-Ansicht übergeben werden, damit ich mit diesen Daten in der von mir erstellten swiftUI-Ansicht arbeiten kann. Zum Beispiel werde ich bestimmte Daten anzeigen, je nachdem welches Bild erkannt wird.
Ich habe andere Fragen zum Stackoverflow gefunden, in denen erläutert wird, wie Daten zwischen Viewcontrollern übertragen werden, nicht jedoch zwischen einem Viewcontroller und einer SwiftUI-Ansicht.
Unten ist mein Code.
Hier ist meine ViewController.swift-Datei
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
}
}
und hier ist meine swiftUI view datei
import SwiftUI
struct imageView: View {
var imageName: String
var body: some View {
ZStack{
Color.white
Text("hello \(imageName)")
}
}
}
Antworten
Sie möchten datosan den Konstruktor der Ansicht übergeben werden, aber das einzige, was datosSie in Ihrem Code haben, ist eine lokale Variable in einem Abschluss.
Sie müssen eine neue Eigenschaft in der VC erstellen
var datos: [[String]]?
Wenn Sie die Daten erhalten, speichern Sie sie in dieser Eigenschaft
self.datos = ....
Wenn Sie dann die Ansicht erstellen, übergeben Sie self.datos