`SwiftUI` - `EnvironmentObject`、`EnvironmentValues` 不会传播到模态呈现的 `UIViewController`

Tac*_*Lee 3 uikit ios swift swiftui

SwiftUI如果视图层次结构设置正确,EnvironmentObjectEnvironmentValues应该传播到子级 - 这对于纯视图层次结构的情况似乎是正确的SwiftUIUIKit当父视图控制器字面上包含其子视图时(例如;UITabViewController、 、 ...) ,情况混合也是如此UINavigationController

但是视图层次结构UIKit上模态呈现的视图控制器SwiftUI不会从其父级获取环境。这是我的设置。

// 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
            }
    }

}
Run Code Online (Sandbox Code Playgroud)

TabBarController实现中,我设置了三个选项卡及其根视图FooBar,并且它呈现了一个模式视图控制器及其根视图FooBar。除了FooBar打印出现的值之外什么也不做。我设置为 3 以覆盖其默认值。选项卡组件打印 3,而显示的视图则打印(这是默认值)。lineLimitEnvironmentValueslineLimitnil

我做错了什么,或者这是被禁止的?如果是这样,那就很奇怪了,因为sheet()框架SwiftUI确实按预期工作(尽管我无法使用此 API,因为我需要完全控制UIViewController演示文稿来应用自定义转换)。

Pav*_*lec 5

完整的环境(值加对象)可以传递给手动创建的UIHostingController来呈现。

这并不明显,但这种技术有效:

1. 获取整个环境
Option a)

// In any view context (= also in `UIViewControllerRepresentable`)
@Environment(\.self) var environment

Option b)

// From `UIViewControllerRepresentableContext` in `updateUIViewController`

let environment = context.environment
Run Code Online (Sandbox Code Playgroud)
2. 在需要的地方重新注入
UIHostingController(
  rootView: presentedScreen
    .environment(\.self, environment)
)
Run Code Online (Sandbox Code Playgroud)