I have a SwiftUI project that uses EnvironmentObject to update a label accordingly. In the same project, I have a UIViewController, that I am hosting in my SwiftUI view by conforming that view controller to the UIViewControllerRepresentable protocol. I want to be able to control the label in my SwiftUI view from my UIKit code. Is there a way I can pass the EnvironmentObject from my UIKit code? If not, what would be the ideal way to pass data from my UIKit based view to the SwiftUI view.
Please note, I have simplified the project for the sake of posting the question here. Here is the code:
MyApp.swift
import SwiftUI
@MainActor class Options: ObservableObject {
@Published var option = 1
}
@main
struct MyApp: App {
@StateObject var options = Options()
var body: some Scene {
WindowGroup {
ContentView().environmentObject(options)
}
}
}
ContentView.swift
import SwiftUI
struct ContentView: View {
@EnvironmentObject var options: Options
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
if options.option == 0 {
Text("Hello, world!")
} else {
Text("Other Options")
}
MyUIView()
}
.padding()
}
}
#Preview {
ContentView().environmentObject(Options())
}
MyUIViewController.swift
import UIKit
class MyUIViewController: UIViewController {
var btn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
var config = UIButton.Configuration.filled()
config.title = "Change Option"
btn = UIButton(configuration: config)
btn.addAction(UIAction(handler: { UIAction in
/* Here, I need to change the option
and pass it to update the label in my SwiftUI view. */
}), for: .touchUpInside);
btn.frame = CGRect(x: 0, y: 0, width: 100, height: 50)
self.view.addSubview(btn)
}
}
MyUIView.swift
import SwiftUI
struct MyUIView: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIViewController {
return MyUIViewController()
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
}
}
Naturally, you should add a
Optionsproperty in your view controller:Then in the
UIViewControllerRepresentable, get theEnvironmentObjectthe same way as usual. Then you can assign it to theoptionsproperty in the view controller: