how to push ViewController from inside UIHostingController's SwiftUI view using pushViewController?

huangapple go评论97阅读模式
英文:

how to push ViewController from inside UIHostingController's SwiftUI view using pushViewController?

问题

我有一个使用UIHostingController来显示SwiftUI视图的UiKit应用程序。在这个视图中有一个按钮,我想要使用它来导航到另一个ViewController。我如何可以从这个SwiftUI视图内部推出一个新的ViewController?(或更一般地说:我如何可以从SwiftUI视图内部调用ViewController中的函数?)

当然,我可以在SwiftUI内部使用NavigationView,但我想要尽可能多地使用UiKit,以便在业务逻辑和UI之间实现清晰的分离。

  1. import UIKit
  2. import SwiftUI
  3. class MainViewController: UIViewController {
  4. var viewModel = ViewModel()
  5. override func viewDidLoad() {
  6. super.viewDidLoad()
  7. addView()
  8. }
  9. func addView() {
  10. let testView = SwiftUIView(viewModel: viewModel)
  11. let controller = UIHostingController(rootView: testView)
  12. addChild(controller)
  13. controller.view.translatesAutoresizingMaskIntoConstraints = false
  14. view.addSubview(controller.view)
  15. controller.didMove(toParent: self)
  16. NSLayoutConstraint.activate([
  17. controller.view.widthAnchor.constraint(equalTo: view.widthAnchor),
  18. controller.view.heightAnchor.constraint(equalTo: view.heightAnchor),
  19. controller.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
  20. controller.view.centerYAnchor.constraint(equalTo: view.centerYAnchor)
  21. ])
  22. }
  23. func navigate() { // 我如何可以从SwiftUI的testView视图内部调用这个函数?
  24. let otherView = Text("test")
  25. let nextVc = UIHostingController(rootView: otherView)
  26. navigationController?.pushViewController(nextVc, animated: true)
  27. }
  28. }

SwiftUI部分如下:

  1. import SwiftUI
  2. struct SwiftUIView: View {
  3. @ObservedObject var viewModel: ViewModel
  4. var body: some View {
  5. Button {
  6. // 推出新的视图控制器
  7. // 你可以在这里调用MainViewController的navigate()函数
  8. } label: {
  9. Text("go")
  10. }
  11. }
  12. }
英文:

I have a UiKit app using a UIHostingController to show a SwiftUI view. In this view there is a button, which I want to use to navigate to another ViewController. How can I push a new viewController from inside this SwiftUI view? (or more generally: how can I call a function from my ViewController from inside the SwiftUI view?)

Of course I could just NavigationView inside SwiftUI, but I want to do most with UiKit, in order to have clean separation between business logic and UI.


  1. import UIKit
  2. import SwiftUI
  3. class MainViewController: UIViewController {
  4. var viewModel = ViewModel()
  5. override func viewDidLoad() {
  6. super.viewDidLoad()
  7. addView()
  8. }
  9. func addView() {
  10. let testView = SwiftUIView(viewModel: viewModel)
  11. let controller = UIHostingController(rootView: testView)
  12. addChild(controller)
  13. controller.view.translatesAutoresizingMaskIntoConstraints = false
  14. view.addSubview(controller.view)
  15. controller.didMove(toParent: self)
  16. NSLayoutConstraint.activate([
  17. controller.view.widthAnchor.constraint(equalTo: view.widthAnchor),
  18. controller.view.heightAnchor.constraint(equalTo: view.heightAnchor),
  19. controller.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
  20. controller.view.centerYAnchor.constraint(equalTo: view.centerYAnchor)
  21. ])
  22. }
  23. func navigate() { // how do I call this from inside SwiftUI testView view?
  24. let otherView = Text("test")
  25. let nextVc = UIHostingController(rootView: otherView)
  26. navigationController?.pushViewController(nextVc, animated: true)
  27. }
  28. }

with the SwiftUI being something like:

  1. import SwiftUI
  2. struct SwiftUIView: View {
  3. @ObservedObject var viewModel: ViewModel
  4. var body: some View {
  5. Button {
  6. // push new view controller
  7. } label: {
  8. Text("go")
  9. }
  10. }
  11. }

答案1

得分: 1

使你的MainViewController成为ObservableObject

testView上设置环境对象

在视图内部使用@EnvironmentObject var parent: MainViewController访问你的环境对象

  1. class MainViewController: UIViewController, ObservableObject {
  2. var viewModel = ViewModel()
  3. override func viewDidLoad() {
  4. super.viewDidLoad()
  5. addView()
  6. }
  7. func addView() {
  8. let testView = SwiftUIView(viewModel: viewModel)
  9. let controller = UIHostingController(rootView: testView.environmentObject(self))
  10. addChild(controller)
  11. controller.view.translatesAutoresizingMaskIntoConstraints = false
  12. view.addSubview(controller.view)
  13. controller.didMove(toParent: self)
  14. NSLayoutConstraint.activate([
  15. controller.view.widthAnchor.constraint(equalTo: view.widthAnchor),
  16. controller.view.heightAnchor.constraint(equalTo: view.heightAnchor),
  17. controller.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
  18. controller.view.centerYAnchor.constraint(equalTo: view.centerYAnchor)
  19. ])
  20. }
  21. }
  22. struct SwiftUIView: View {
  23. @EnvironmentObject var parent: MainViewController
  24. var body: some View {
  25. Button {
  26. // 推入新的视图控制器
  27. parent.navigationController?.pushViewController(<#T##viewController: UIViewController##UIViewController#>, animated: <#T##Bool#>)
  28. } label: {
  29. Text("go")
  30. }
  31. }
  32. }
英文:

Make your MainViewController as ObservableObject

Set environment object on testView

Access your environment object inside your view using @EnvironmentObject var parent: MainViewController

  1. class MainViewController: UIViewController, ObservableObject {
  2. var viewModel = ViewModel()
  3. override func viewDidLoad() {
  4. super.viewDidLoad()
  5. addView()
  6. }
  7. func addView() {
  8. let testView = SwiftUIView(viewModel: viewModel)
  9. let controller = UIHostingController(rootView: testView.environmentObject(self))
  10. addChild(controller)
  11. controller.view.translatesAutoresizingMaskIntoConstraints = false
  12. view.addSubview(controller.view)
  13. controller.didMove(toParent: self)
  14. NSLayoutConstraint.activate([
  15. controller.view.widthAnchor.constraint(equalTo: view.widthAnchor),
  16. controller.view.heightAnchor.constraint(equalTo: view.heightAnchor),
  17. controller.view.centerXAnchor.constraint(equalTo: view.centerXAnchor),
  18. controller.view.centerYAnchor.constraint(equalTo: view.centerYAnchor)
  19. ])
  20. }
  21. }
  22. struct SwiftUIView: View {
  23. @EnvironmentObject var parent: MainViewController
  24. var body: some View {
  25. Button {
  26. // push new view controller
  27. parent.navigationController?.pushViewController(&lt;#T##viewController: UIViewController##UIViewController#&gt;, animated: &lt;#T##Bool#&gt;)
  28. } label: {
  29. Text(&quot;go&quot;)
  30. }
  31. }
  32. }

答案2

得分: 0

调用此函数在你的按钮点击事件上。尽量使这个函数全局可用,这样你可以从任何SwiftUI视图中访问它。

  1. func navigateToViewController(view: View)
  2. {
  3. let newVC = UIHostingController(rootView: view)
  4. newVC.modalPresentationStyle = .overCurrentContext
  5. let transition = CATransition()
  6. transition.duration = 0.3
  7. transition.type = CATransitionType.push
  8. transition.subtype = CATransitionSubtype.fromRight
  9. transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
  10. UIApplication.shared.windows[0].rootViewController!.view.window!.layer.add(transition, forKey: kCATransition)
  11. UIApplication.shared.windows[0].rootViewController!.present(newVC, animated: false, completion: nil)
  12. }
英文:

call this function on your button-click event. try to make this function global so you can access it from every swiftUI View.

  1. func navigateToViewController(view : any View)
  2. {
  3. let newVC = UIHostingController(rootView: view)
  4. newVC.modalPresentationStyle = .overCurrentContext
  5. let transition = CATransition()
  6. transition.duration = 0.3
  7. transition.type = CATransitionType.push
  8. transition.subtype = CATransitionSubtype.fromRight
  9. transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
  10. UIApplication.shared.windows[0].rootViewController!.view.window!.layer.add(transition, forKey: kCATransition)
  11. UIApplication.shared.windows[0].rootViewController!.present(newVC, animated: false, completion: nil)
  12. }

huangapple
  • 本文由 发表于 2023年3月3日 21:23:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/75627630.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定