SwiftUI:如何从NavigationView

时间:2019-09-22 13:51:17

标签: uinavigationcontroller uikit swiftui

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

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

一种框架方法期望参数类型为UINavigationController

如何为SwiftUI创建的NavigationControlle r提供此框架?或者如何创建UINavigationController来取代SwiftUI的默认设置?

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

3 个答案:

答案 0 :(得分:2)

我认为您现在无法做到。看着NavigationView的视图调试器,我得到下面的图像。

因此,您似乎必须采取另一种方法:
UINavigationController开始,然后将SwiftUI视图包装在UIHostingController中。

enter image description here

答案 1 :(得分:1)

由于Yonat的解释,我了解如何做到这一点,这是我的解决方案,希望它能对其他人有所帮助。

第1部分:将在Swift UI中使用的UI View Controller。它调用第三方认证库,并传递UINavigationControler作为参数。 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 
                // ...
            }
        }
    }
}

答案 2 :(得分:0)

我试图做同样的事情,因为我想让InteractivePopGestureRecognizer在整个视图上都能工作。

我设法使用UINavigationController扩展并覆盖viewDidAppear来访问当前的导航控制器,检查是否启用了InteractivePopGestureRecognizer并对其进行了更改(https://stackoverflow.com/a/58068947/1745000

最后,我的努力毫无意义。导航视图显示DetailHostingController时,它会关闭InteractivePopGestureRecognizer.isEnabled!

通过topViewController.view进行的托管视图确实包含私有类型SwiftUI.UIGestureRecognizer的手势识别器。尽管未设置目标...

最好嵌入传统的UINavigationController,因为导航视图自己的弹出手势无法取消(如果将视图拖动一点并停止,它会回弹然后关闭详细视图。