How to pass data between UIViewController
and struct ContentView
?
I tried with ObservableObject
but I can't get the data up to date.
First, use binding to your input view. And for action use closure to get action from SwiftUI to UIKit. Here is a possible solution. override func viewDidLoad() { super.
The UIViewRepresentable protocol allows you to adapt to the mechanism of SwiftUI declarative views and creates a bridge between UIKit and SwiftUI. Whether it's a custom UIView created by yourself or a UIView provided by Apple that isn't available in UIKit yet: you can make them available in SwiftUI.
A UIKit view controller that manages a SwiftUI view hierarchy.
To pass data from a UIViewController
to an SwiftUI-Struct inside an UIHostingController
you can attach an environmentObject
to the SwiftUI rootView
:
let vc = UIHostingController(rootView: YourContentView().environmentObject(yourEnvironmentObject))
Of course you'll need to create an ObservableObject and add it to your SwiftUI-Struct.
Create the ObservableObject:
class TypeOfEnvironmentObject: ObservableObject {
@Published var data = "myData"
}
Add it to your struct:
@EnvironmentObject var yourEnvironmentObject: TypeOfEnvironmentObject
I found the existing answers confusing/incomplete, perhaps something changed around generic inference in Swift 5.3 etc. While you can add an environment object to the UIHostingController's view this seems to conflict with the types (i.e. the generic parameter to UIHostingController needs a concrete type). Adding AnyView
resolves this:
import UIKit
import SwiftUI
struct TutorialView: View {
@EnvironmentObject private var integration: TutorialIntegrationService
var body: some View {
Text("Hi").navigationBarTitle("test: \(integration.id)")
}
}
class TutorialIntegrationService: ObservableObject {
@Published var id: Int = 0
}
class TutorialViewController: UIHostingController<AnyView> {
let integration = TutorialIntegrationService()
required init?(coder: NSCoder) {
super.init(coder: coder,rootView: AnyView(TutorialView().environmentObject(integration)));
}
}
Add class myclassname: ObservableObject
In the class create a variable with @Published var myvar
and add:
init(myvar: type) {
self.myvar = myvar
}
In UIViewController
add:
private var model = myclassname(myvar: XXX)`
and in viewWillAppear
add:
let vc = myclassname(myvar: myvar)
let childView = UIHostingController(rootView: ContentView(model: vc))
In the struct
add:
@ObservedObject var model: myclassname
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With