如何从SwiftUI视图导航到UIKit UIViewController

时间:2020-02-19 18:03:44

标签: swift uiviewcontroller uikit swiftui swiftui-navigationlink

到目前为止,我已经完全使用UIKit构建了一个应用程序。但是,我希望能够开始实现一些SwiftUI视图来替换某些UIViewControllers。

通过单击按钮,我已经能够从UIViewController导航到SwiftUI View

    @IBAction func buttonTapped(_ sender: Any) {
        let newView = UIHostingController(rootView: SwiftUIView(viewObj: self.view, sb: self.storyboard, dismiss: self.dismiss) )
        view.window?.rootViewController = newView
        view.window?.makeKeyAndVisible()
    }

我的问题是,如何从单个SwiftUI视图过渡到UIViewController?(因为应用程序的其余部分在UIKit中)?我在SwiftUI视图中有一个按钮,可以在点击时导航回UIViewController。我尝试过:

  1. viewstoryboard对象传递给SwiftUI视图,然后调用做与上述代码相似的操作来更改当前视图控制器。但是,当在模拟器上尝试时,什么也没发生。
  2. 使用.present以模态显示SwiftUI视图。这可行,我可以允许SwiftUI视图本身为.dismiss。但是,这只能以模态方式起作用,我希望可以使其正常工作(即更改屏幕)

这是我简单的SwiftUI视图:

struct SwiftUIView: View {
    var viewObj:UIView? // Perhaps use this for transition back?
    var sb:UIStoryboard?
    var dismiss: (() -> Void)?

    var body: some View {

        Button(action: {
            // Do something here to Transition
        }) {
            Text("This is a SwiftUI view.")
        }
    }
}

我无法理解如何将SwiftUI正确集成到UIKit中,,并且我不确定UIViewControllerRepresentable是否是答案。非常感谢对此的任何解决方案,替代方案或有用的知识。再次感谢!

2 个答案:

答案 0 :(得分:2)

Ciao

我尝试通过使用闭包回调来遵循您的方法。

struct SwiftUIView: View {
    var dismiss: (() -> Void)?
    var present: (()->Void)?

    var body: some View {
        VStack(spacing: 20) {
            Button(action: {
                self.dismiss?()
            }) {
                Text("Dismiss me")
            }
            Button(action: {
                self.present?()
            }) {
                Text("Present some UIViewController")
            }
        }
    }
}

当您呈现UIHostingController时,您想要实现2个闭包回调:

@IBAction func buttonTapped(_ sender: Any) {
    let hostingController = UIHostingController(rootView: SwiftUIView())
    hostingController.rootView.dismiss = {
        hostingController.dismiss(animated: true, completion: nil)
    }
    hostingController.rootView.present = {
        let destination = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "VC_TO_PRESENT")
        hostingController.present(destination, animated: true, completion: nil)
    }

    present(hostingController, animated: true, completion: nil)
}

答案 1 :(得分:0)

您只能以镜像顺序执行相同操作,例如跟随(抓痒)...

    Button(action: {
        if let vc = self.sb?.instantiateViewController(withIdentifier: "some_identifier") {
            self.viewObj?.window?.rootViewController = vc
            // or via present as alternate
            // self.viewObj?.window?.rootViewController.present(vc, animated: true, completion: nil)
        }
    }) {