2

This is my first time working in Xcode and I am building an app using Storyboards/View Controllers. However, I have a page I want to display using SwiftUI, which I am doing through a host controller. I want to be able to assign a value to a variable in my ViewController code and then access this value in my swiftUI ContentView file. I feel like there should be a simple solution, but I can't seem to find a way to share data between the two. Thank you for any help.

2 Answers 2

6

Here is a simple method to see how to pass data to SwiftUI View from UIKit UIViewController. Here I'm passing a simple text setting it in the initializer of ContentView and presenting the UIHostingController on ViewController. Here is the code:

import UIKit
import SwiftUI
import PlaygroundSupport

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(action))
    }

    @objc func action() {
        let contentView = ContentView(text: "My Text")
        let viewController = UIHostingController(rootView: contentView)
        present(viewController, animated: true)
    }
}


struct ContentView: View {

    var text: String

    var body: some View {
        Text(text)
    }
}

PlaygroundPage.current.setLiveView(UINavigationController(rootViewController: ViewController()))
PlaygroundPage.current.needsIndefiniteExecution = true

You can copy/paste this code on your playground to see how it works.

Sign up to request clarification or add additional context in comments.

Comments

2

Assuming you are using a UIHostingController and a story board segue, you can use the prepare for segue function to set a value in the rootView of the hosting view controller.

For example:

UIViewController

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "theSegue" {
            let dest = segue.destination as! TheHostingViewController
            dest.rootView.theString = "This is the String to pass"
        }
    }

}

UIHostingController

import UIKit
import SwiftUI

class TheHostingViewController: UIHostingController<TheSwiftUIView> {
    
    required init?(coder aDecoder: NSCoder){
        super.init(coder: aDecoder, rootView: TheSwiftUIView())
    }

    
    override func viewDidLoad() {
        super.viewDidLoad()

    }

}

SwiftUI view

import SwiftUI

struct TheSwiftUIView: View {
    
    var theString: String?

    var body: some View {
        Text(theString!)
    }
}

StoryBoard

Be sure to change the Class of the Hosting Controller to the name of your UIHostingController in interface builder (as shown in the image below).

Interface Builder

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.