【问题标题】:How to navigate back to UIViewController from SwiftUI View?如何从 SwiftUI View 导航回 UIViewController?
【发布时间】:2021-05-25 07:29:43
【问题描述】:

我在所有视图中都使用 SwiftUI 1.0,从 MainView 开始,这是除了登录之外的主屏幕,因为我使用的是通过 UIKit 制作的客户端 LoginSDK。

所以在 LoginViewController 中,我可以使用以下代码在成功登录时推送 MainView():

func showMainView() {
    let host = UIHostingController(rootView: MainView())
    self.navigationController?.navigationBar.isHidden = true
    self.navigationController?.pushViewController(host, animated: true)
}

在 MainView 中,我尝试实现一个注销方法,当用户使用以下代码单击注销按钮时,该方法将 LoginViewController 设置为 rootView:

struct MainView: View {
    
    var body: some View {
            NavigationView {
                    VStack {
                        Button(action: {
                           logout()
                        }, label: {
                            Image("Logout")
                                .resizable()
                                .frame(width: 20, height: 16)
                        })
                    }
            }
    }

  //Method to logout and set the RootNavigationViewController as rootViewController
  func logout () {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    //The LoginViewController is embedded in RootNavigationViewController
    let rootViewController = storyboard.instantiateViewController(withIdentifier: "RootNavigationViewController") as! UINavigationController
            
    if let window = UIApplication.shared.windows.first {
        window.rootViewController = rootViewController
        window.endEditing(true)
        window.makeKeyAndVisible()
    }
  }

}

上面的注销方法实现什么都不做。我想知道如何从 MainView(一个 SwiftUI 结构)导航回 LoginViewController(一个 UIKit UIViewController)。

【问题讨论】:

  • 尝试呈现而不是推送视图。另一件事是您可以使用绑定来显示/隐藏视图。
  • @Rj19,谢谢你的回答,但业务需求是从 LoginViewController 推送 MainView。此外,对于显示和隐藏视图,您是否已经尝试过同时使用 UIKit 的 UIViewController 和 SwiftUI 的视图?如果是的话,你能参考一些代码吗?谢谢!
  • 我用来显示和隐藏的是绑定,因为它非常简单且富有表现力。但是,您的情况可能会有所不同。仍然在这里是链接:swiftwithmajid.com/2020/04/08/binding-in-swiftui

标签: ios swiftui uikit swiftui-navigationview uihostingcontroller


【解决方案1】:

这对我来说非常有效,我希望这会有所帮助!

let storyboard = UIStoryboard(name: "Main", bundle: nil)

let rootViewController = storyboard.instantiateViewController(withIdentifier: "YourIdentifier")

           if let window = UIApplication.shared.windows.first {
               window.rootViewController = rootViewController
               window.endEditing(true)
               window.makeKeyAndVisible()
           }

【讨论】:

    【解决方案2】:

    可能的解决方案是使用类似回调

    struct MainView: View {
        var didLogout: () -> ()
        
        // ... other code
    
      func logout () {
        // ... make logout activity here and on completion perform
    
        // DispatchQueue.main.async {  << if logout callback in different queue
           didLogout()
        // }
      }
    }
    

    现在我们可以把它当作

    func showMainView() {
        let host = UIHostingController(rootView: MainView() { [weak self] in
           self?.navigationController?.popViewController(animated: true)  // << here !!
        })
    
        self.navigationController?.navigationBar.isHidden = true
        self.navigationController?.pushViewController(host, animated: true)
    }
    

    【讨论】:

    • 您好 Asperi,感谢您的回答。我尝试了这个实现,它在某种意义上是部分工作的,它在触发回调时弹出到 LoginViewController。但是当用户已经登录时,rootViewController 将是 MainView,因此弹出到 LoginViewController 的回调不再起作用。您是否知道另一种直接在 SwiftUI 的某个函数调用上设置 rootview 的实现,该函数调用将导航回 UIKit 的 LoginViewController?提前致谢!
    猜你喜欢
    • 2020-06-19
    • 2020-06-03
    • 1970-01-01
    • 2021-04-06
    • 2020-12-26
    • 1970-01-01
    • 2021-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多