Search code examples
iosswiftuiios13navigationlink

Supporting SwiftUI navigation in legacy projects


I'm wondering if there's any way to start using SwiftUI in a legacy project and still be able to navigate back and forth SwiftUI scenes. That is, let's imagine I just want to support the last iOS 13 for a project I've been working on for the last year. Everything is built upon UIKit and navigations happen the usual way presenting or pushing viewcontrollers.

Now I want to start using SwiftUI so I enable the option in the General of my project, target iOS 13, get my SceneDelegate and my new key-value pair in Info.plist. In order to navigate to a Swift UI scene, I can just push a UIHostingViewController whose rootView will be my newly designed SwiftUI View. But how can I use NavigationLink to push an old UIKit view controller?

class ViewController: UIViewController {

    @IBAction func userDidTapGo(_ sender: Any) {
        let contentView = ContentView()
        navigationController?.pushViewController(UIHostingController(rootView: contentView), animated: true)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        title = "UIKit"
    }
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            NavigationLink(destination: /* what should be here?? */) {
                Text("Go to UIKit")
            }

        }.navigationBarTitle("Swift UI")
    }
}

Solution

  • You'll need to wrap you old view controllers in a UIViewControllerRepresentable wrapper. There is a nice tutorial by Apple: Interfacing with UIKit.

    It works great, lets you reuse old code instead of rewriting everything from scratch.