5

I can't find a way or a good tutorial to explain how to pass the value of a variable (String or Int) that is owned by a UIViewController to a SwiftUI view that is calling the view.

For example:

class ViewController: UIViewController {
    var myString : String = "" // variable of interest
    ....
    
    func methodThatChangeValueOfString(){
        myString = someValue
    }
}

// to make the view callable on SwiftUI
extension ViewController: UIViewControllerRepresentable {
    typealias UIViewControllerType = ViewController
    
    public func makeUIViewController(context: UIViewControllerRepresentableContext<ViewController>) -> ViewController {
        return ViewController()
    }
    
    func updateUIViewController(_ uiViewController: ViewController, context: UIViewControllerRepresentableContext<ViewController>) {
        
    }
    
}

In SwiftUI I'll have

struct ContentView: View {
    var body: some View {
        ViewController()
    }
}

How can I take myString of the ViewController and use it in ContentView? Thanks in advance

2
  • There are several approaches, but it is not very clear the goal. Commented Oct 17, 2020 at 14:52
  • Ok, I'll explain my specific problem. In the ViewController I have the camera and with Vision I make object detection. The name of the object detected by the camera is saved in a variable as a String. I want to print the string on screen using SwiftUI but I can't pass the data to my SwiftUI View. Commented Oct 17, 2020 at 14:56

1 Answer 1

9

Use MVVM pattern it is what is recommended with SwiftUI.

Share a ViewModel between your SwiftUI View and your UIKit ViewController.

I suggest you start with the basic Apple SwiftUI tutorials. Specifically how to "Interface with UIKit"

https://developer.apple.com/tutorials/swiftui/interfacing-with-uikit

import SwiftUI

struct SwiftUIView: View {
    @StateObject var sharedVM: SharedViewModel = SharedViewModel()
    var body: some View {
        VStack{
            UIKitViewController_UI(sharedVM: sharedVM)
            Text(sharedVM.myString)
        }
    }
}

class SharedViewModel: ObservableObject{
    @Published var myString = "init String"
}
//Not an extension
struct UIKitViewController_UI: UIViewControllerRepresentable {
    typealias UIViewControllerType = UIKitViewController
    var sharedVM: SharedViewModel
    
    func makeUIViewController(context: Context) -> UIKitViewController {
        return UIKitViewController(vm: sharedVM)
    }
    
    
    func updateUIViewController(_ uiViewController: UIKitViewController, context: Context) {
        
    }
    
}
class UIKitViewController: UIViewController {
    let sharedVM: SharedViewModel
    
    var runCount = 0
    
    init(vm: SharedViewModel) {
        self.sharedVM = vm
        super.init(nibName: nil, bundle: nil)
        //Sample update mimics the work of a Delegate or IBAction, etc
        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
            self.runCount += 1
            self.methodThatChangeValueOfString()
            if self.runCount == 10 {
                timer.invalidate()
            }
        }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func methodThatChangeValueOfString(){
        sharedVM.myString = "method change" + runCount.description
    }
}

struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        SwiftUIView()
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Is there a way to create the UIKitViewController_UI in the View struct as a variable and then pass on the sharedVM? I need to call some functions in the UIKitViewController_UI from within the view. However, it calls an 'self' used before all stored properties are initialized error when I try to do this.
@Björn You could create it, but it likely wouldn’t work properly because it would be in a class SwiftUI Views should stay in struct. Ask a question and people can look at your Minimal Reproducible Example but it sounds like you are just setting the variable too soon.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.