SwiftUI
's EnvironmentObject
s and EnvironmentValues
should propagate to children if view hierarchy is set properly - this seems to be true for a case of pure SwiftUI
view hierarchy. Also true for case mixing with UIKit
when parent view controller literally contains its children (for example; UITabViewController
, UINavigationController
, ...).
But modally presented UIKit
view controller on SwiftUI
view hierarchy does not get the environments from its parent. Here are my setups.
// ContentView
struct ContentView: View {
var body: some View {
TabBarController()
.environment(\.lineLimit, 3) // override default value of lineLimit
}
}
// TabBarController
struct TabBarController: UIViewControllerRepresentable {
typealias UIViewControllerType = UITabBarController
func makeUIViewController(context: Context) -> UIViewControllerType {
let uiViewController = UITabBarController()
uiViewController.setViewControllers([
UIHostingController(rootView: FooBar()),
UIHostingController(rootView: FooBar()),
UIHostingController(rootView: FooBar())
], animated: false)
return uiViewController
}
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
// For test purpose, present view controller modally
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
uiViewController.present(UIHostingController(rootView: FooBar()), animated: true)
}
}
}
// FooBar
struct FooBar: View {
@Environment(\.lineLimit) var lineLimit
var body: some View {
Text("Hello World!")
.onAppear {
print(lineLimit) // prints given environment value
}
}
}
In TabBarController
implementation I set up three tabs with their root view FooBar
, and it presents a modal view controller with its root view FooBar
. FooBar
does nothing but prints value of lineLimit
from its EnvironmentValues
on appear. I set lineLimit
to 3 to override its default value. The tab components prints 3, whereas the presented view prints nil
(which is default value).
What am I doing wrong, or is it prohibited? Weird if it is, because sheet()
from SwiftUI
framework does work as expected (though I cannot use this API because I need full control of UIViewController
presentation to apply custom transition ).
SwiftUI's EnvironmentObjects
and EnvironmentValues
should propagate ONLY to SwiftUI children views . For other (trans-framework/API) cases we have to do this manually, like
struct TabBarController: UIViewControllerRepresentable {
@Environment(\.lineLimit) var lineLimit // << here !!
typealias UIViewControllerType = UITabBarController
func makeUIViewController(context: Context) -> UIViewControllerType {
let uiViewController = UITabBarController()
uiViewController.setViewControllers([
UIHostingController(rootView:
FooBar().environment(\.lineLimit, lineLimit)), // << here !!
UIHostingController(rootView: FooBar()),
UIHostingController(rootView: FooBar())
], animated: false)
return uiViewController
}
// ... other code
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.