Josh Byanec McFergan
Josh Byanec McFergan

Reputation: 491

How to navigate back to UIViewController from SwiftUI View?

I'm using SwiftUI 1.0 in all my views starting from MainView which is the Home screen other than the Login as I'm using a client LoginSDK which is made via UIKit.

So in LoginViewController, I'm able to push the MainView() on sucessful login with code below:

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

In the MainView, I have tried implementing a logout method that sets the LoginViewController as the rootView when the user clicks the logout Button with the code below:

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()
    }
  }

}

The above logout method implementation is doing nothing. I would like to know how can I navigate back to LoginViewController (A UIKit UIViewController) from MainView (A SwiftUI struct).

Upvotes: 3

Views: 2546

Answers (2)

Wilkens Lavarin
Wilkens Lavarin

Reputation: 11

This worked perfectly for me, I hope this helps!

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()
           }

Upvotes: 1

Asperi
Asperi

Reputation: 257859

Possible solution is to use callback like

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()
    // }
  }
}

and now we can use it as

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

Upvotes: 1

Related Questions