Wie übergebe ich Daten von viewController an swiftUI view?

Sep 23 2020

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

1 LouFranco Sep 24 2020 at 17:26

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