首页 > 解决方案 > SwiftUI:如何从 NavigationView 访问 UINavigationController

问题描述

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

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

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

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

我阅读了https://developer.apple.com/tutorials/swiftui/interfacing-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

标签: uinavigationcontrolleruikitswiftui

解决方案


感谢 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)
    }

}

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

推荐阅读