SwiftUI
的EnvironmentObject
s和EnvironmentValues
应该传播到孩子,如果视图层次设置正确-这似乎是真正的纯SwiftUI
视图层次的情况。当父视图控制器实际上包含其子视图控制器时,与UIKit
大小写混合也是如此(例如; UITabViewController
,UINavigationController
,...)。
但是,在SwiftUI
视图层次结构上以模态方式呈现的UIKit
视图控制器并不从其父视图层次结构获取环境。这是我的设置。
// 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
}
}
}
在TabBarController
实现中,我设置了三个选项卡,它们的根视图为FooBar
,它提供了一个模态视图控制器,其根视图为FooBar
。FooBar
什么也不做,只是打印lineLimit
的值,从它的EnvironmentValues
出现。我将lineLimit
设置为3以覆盖其默认值。选项卡组件打印3,而显示的视图打印nil
(默认值)。
我做错了什么,还是被禁止了?如果是这样的话,那就太奇怪了,因为SwiftUI
框架的sheet()
确实能按预期工作(尽管我不能使用这个API,因为我需要完全控制UIViewController
的表示来应用自定义转换)。
2条答案
按热度按时间jgwigjjp1#
SwiftUI的
EnvironmentObjects
和EnvironmentValues
应该传播ONLY到SwiftUI子视图。对于其他(跨框架/API)的情况,我们必须手动执行此操作,例如xxls0lw82#
理想情况下,
UIHostingController.init
可以选择接受Context
(沿着它的UIViewControllerRepresentableContext
),然后将整个环境进一步传递给所呈现的SwiftUI视图。可悲的是,事实并非如此。一种可能的解决方案可以避免现有的不可扩展的解决方案,即手动逐个键地传递所有必要的环境值(有时在模块化架构中甚至不可能):
1.创建一个自定义的 Package 器来封装所有的环境值:
1.将其馈送到应呈现的
UIHostingController
1.在目标SwiftUI视图中使用它,可以动态地:
或者,假设这个视图总是只从UIKit中呈现