Lucas Goldner
Lucas Goldner

Reputation: 730

How to go back from a SwiftUI View inside a to UIKit?

I have a SwiftUI inside a HostingViewController and a UIKit Viewcontroller. My goal is to switch between them with a button press. The problem is I cannot achieve to go from my SwiftUI View inside the HostingViewController back to UIKit.

I can go to the HostingViewController over my UIKit ViewController with this segue function:

 @IBSegueAction func swiftUIAction(_ coder: NSCoder) -> UIViewController? {
        return UIHostingController(coder: coder, rootView: WorkoutSelectView())
    }

What I have tried

But I do not know how to go back. I have used a solution where I call a function from my AppDelegate of my SwiftUI View here:

 guard let appDelegate: AppDelegate = UIApplication.shared.delegate as? AppDelegate else { return }
 appDelegate.switchBack()

and inside the Appdelegate I have this function:

 func switchBack(){
        guard var rootViewController = (UIApplication.shared.connectedScenes.first?.delegate as? SceneDelegate)?.window?.rootViewController else {
                  return
        }
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let controller = storyboard.instantiateViewController(withIdentifier: "Home") as! HomeViewController
        rootViewController.present(controller, animated: true, completion: { () -> Void in
        
        })
    }

The cool thing about this it works but the problem is then:

<WorkoutTracker.HomeViewController: 0x148f072a0>) whose view is not in the window hierarchy.

So have you got any ideas ?

Upvotes: 2

Views: 1720

Answers (1)

Asperi
Asperi

Reputation: 258611

The possible approach is to pass completion callback into your SwiftUI view, like in below simplified demo

struct WorkoutSelectView: View {
    var completion: () -> () = {}

    var body: some View {
        Button("Close", action: completion)
    }
}

and use this callback in your UIViewController to dismiss presented controller, like

@IBSegueAction func swiftUIAction(_ coder: NSCoder) -> UIViewController? {
   let controller =  UIHostingController(coder: coder, 
        rootView: WorkoutSelectView() { [weak self] in
           self?.dismiss(true)
        })
   return controller
}

Upvotes: 4

Related Questions