SwiftUI-将视图控制器引用从UIWindowScene传递给视图

时间:2020-09-19 10:27:06

标签: ios uiviewcontroller swiftui presentviewcontroller uiwindowscene

我在SwiftUI中创建了一个应用程序。

视图是结构,但是我需要了解视图控制器,因为它需要呈现一些特殊的警报。

我看到在我的项目中有AppDelegate和SceneDelegate。

我发现了

let contentView = ContentView()

    // Use a UIHostingController as window root view controller.
    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = UIHostingController(rootView: contentView)
        self.window = window
        window.makeKeyAndVisible()
    }

所以我想将视图控制器引用传递给其他视图。

window.rootViewController是传递和使用正确的值吗?

2 个答案:

答案 0 :(得分:0)

可能的解决方案是将托管视图控制器作为环境密钥注入,因此可以在任何ContentView内部层次结构级别使用。

这是一个演示。在Xcode 12 / iOS 14上进行了测试。

  1. 声明环境密钥
struct RootViewControllerKey: EnvironmentKey {
    static let defaultValue: UIViewController? = nil
}

extension EnvironmentValues {
    var rootViewController: UIViewController? {
        get { self[RootViewControllerKey.self] }
        set { self[RootViewControllerKey.self] = newValue }
    }
}
  1. 将环境注入ContentView
if let windowScene = scene as? UIWindowScene {
    let window = UIWindow(windowScene: windowScene)

    let rootController = UIHostingController(rootView: AnyView(EmptyView()))
    rootController.rootView = AnyView(contentView
        .environment(\.rootViewController, rootController))
    window.rootViewController = rootController

    self.window = window
    window.makeKeyAndVisible()
}
  1. 在内部使用
struct ContentView: View {
    // can be used here as well

    var body: some View {
      TestSubView()
    }
}

struct TestSubView: View {
    @Environment(\.rootViewController) var viewController // for demo here!!

    var body: some View {
      Text("Demo")
        .onAppear {
          print(String(describing: self.viewController))
        }
    }
}

答案 1 :(得分:0)

我不知道这个答案是否合适,但它对我有用,所以使用时要小心。

class func getTopMostViewController() -> UIViewController? {
    var topMostViewController = UIApplication.shared.keyWindow?.rootViewController

    while let presentedViewController = topMostViewController?.presentedViewController {
        topMostViewController = presentedViewController
    }

    return topMostViewController
}

使用像这样的值

let viewController=getTopMostViewController()
viewController.present(...

来自 StackOverflow 的回答:

Get top most UIViewController