繁体   English   中英

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

[英]How do I pass data from viewController to swiftUI view?

我正在开发一个使用 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 = ....

然后,当你构造 View 时,通过self.datos

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM