SwiftUI:如何从 NavigationView 访问 UINavigationController

Séb*_*acq 18 uikit uinavigationcontroller swiftui

我正在使用 SwiftUI 开发应用程序。该应用程序基于NavigationView.

我正在使用提供UIKit组件的第三方框架,并且该框架尚未更新以支持 SwiftUI。

一个框架方法需要一个类型的参数 UINavigationController

我怎样才能提供这个NavigationControlle由 SwiftUI 创建的框架?或者我如何创建一个UINavigationController将替换 SwiftUI 的默认值?

我阅读了https://developer.apple.com/tutorials/swiftui/interface-with-uikithttps://sarunw.com/posts/uikit-in-swiftui但这些似乎解决了另一个问题:他们解释了如何使用SwiftUI 应用程序中的 UIKit 组件。我的问题是反过来,我想使用 SwiftUI App 并访问底层 NavigationController 对象。

[更新] 本研讨会提供了实现我的解决方案的代码:https : //amplify-ios-workshop.go-aws.com/30_add_authentication/20_client_code.html#loginviewcontroller-swift

Séb*_*acq 10

感谢 Yonat 的解释,我明白了如何做到这一点,这是我的解决方案,希望它能帮助其他人。

第 1 部分:将从 Swift UI 使用的 UI 视图控制器。它调用第三方身份验证库,传递UINavigationControleras 参数。这UINavigationController是一个空视图,只是为了让第三方身份验证库有一个导航控制器来弹出登录屏幕。

struct LoginViewController: UIViewControllerRepresentable {

    let navController =  UINavigationController()


    func makeUIViewController(context: Context) -> UINavigationController {
        navController.setNavigationBarHidden(true, animated: false)
        let viewController = UIViewController()
        navController.addChild(viewController)
        return navController
    }

    func updateUIViewController(_ pageViewController: UINavigationController, context: Context) {
    }

    func makeCoordinator() -> Coordinator {
        return Coordinator(self)
    }

    class Coordinator: NSObject {
        var parent: LoginViewController

        init(_ loginViewController: LoginViewController) {
            self.parent = loginViewController
        }
    }

    func authenticate() {
        let app = UIApplication.shared.delegate as! AppDelegate
        let userData = app.userData

        userData.authenticateWithDropinUI(navigationController: navController)
    }

}
Run Code Online (Sandbox Code Playgroud)

第 2 部分:Swift UI 视图显示(空)UINavigationControler 并在其上覆盖一个 SwiftUI 视图。

import SwiftUI

struct LandingView: View {
    @ObservedObject public var user : UserData

    var body: some View {

        let loginView = LoginViewController()

        return VStack {

            // .wrappedValue is used to extract the Bool from Binding<Bool> type
            if (!$user.isSignedIn.wrappedValue) {

                ZStack {
                    loginView
                    // build your welcome view here 
                    Button(action: { loginView.authenticate() } ) {
                        UserBadge().scaleEffect(0.5)
                    }
                }

            } else {

                // my main app view 
                // ...
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Yon*_*nat 6

我不认为你现在可以这样做。查看视图调试器,NavigationView我得到了下面的图像。

因此,在您看来,您将不得不反过来:
从 a 开始UINavigationController,然后将 SwiftUI 视图包装在UIHostingController.

在此处输入图片说明