如何将数据从viewController传递到swiftUI视图?

问题描述

我正在开发一个使用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)")
            
        }
            
        
    }
}

解决方法

您希望将datos传递给View的构造函数,但是代码中唯一的datos是闭包中的局部变量。

您需要在VC中创建一个新属性

var datos: [[String]]?

然后,当您获取数据时,将其保存在此属性中

self.datos = ....

然后,在构造视图时,传递self.datos

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...