Come si passano i dati da viewController a swiftUI view?
Sto lavorando a un'app che utilizza ARkit per rilevare le immagini. Quando viene rilevata un'immagine all'interno della cartella delle risorse, l'app mostra una vista swiftUI sopra l'immagine e quando un'immagine non viene più tracciata, la vista swiftUI scompare. Fino a qui funziona tutto bene.
All'interno del metodo viewdidload nel file viewController sto scaricando e analizzando un file csv da Internet. Funziona anche questo.
Dove sto lottando è capire come passare i dati analizzati dal file csv che si trova all'interno di viewdidload alla vista swiftUI, in modo da poter lavorare con questi dati sulla vista swiftUI che sto creando. Ad esempio, mostrerò dati specifici a seconda dell'immagine rilevata.
Ho trovato altre domande su stackoverflow in cui discutono su come passare i dati tra i viewcontroller, ma non tra un viewcontroller e una vista swiftUI.
Di seguito è il mio codice.
Ecco il mio file 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
}
}
ed ecco il mio file di visualizzazione swiftUI
import SwiftUI
struct imageView: View {
var imageName: String
var body: some View {
ZStack{
Color.white
Text("hello \(imageName)")
}
}
}
Risposte
Vuoi datosessere passato al costruttore della vista, ma l'unica datosche hai nel tuo codice è una variabile locale in una chiusura.
Devi creare una nuova proprietà nel VC
var datos: [[String]]?
Quindi, quando ottieni i dati, salvali in questa proprietà
self.datos = ....
Quindi, quando costruisci la vista, passa self.datos