Search code examples
swiftswiftuiuikituinavigationcontrollerswiftui-navigationview

Loading UIkit Views and swiftUI view from SwiftUI NavigationView With stack style navigation


I wanted to create common class for navigation bar and navigationView used throughout the project in SwiftUI.

In my project some of the screens are in UIKit and some of the screens are in UIKIT. What is best architecture to implement such type of navigation class and how to achieve something like that.

For eg:

MainNavigationView.Swift

import SwiftUI
    struct MainNavigationView: View {
        var body: some View {
            NavigationView {
                HomeScreenController {} // UIKIT
            }
        }
    }

HomeScreenController.Swift // UIKIT

override func viewDidLoad() {
  super.viewDidLoad()

  let button = UIButton(frame: CGRect(x: 100, y: 100, width: 100, height: 50))
  button.backgroundColor = .green
  button.setTitle("Test Button", for: .normal)
  button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)

  self.view.addSubview(button)
}

@objc func buttonAction(sender: UIButton!) {
  navigation.push(detailScreen()) // detailScreen here in SWIFTUI
}

DetailScreen.Swift where it can be navigated to SwiftUI or UIKIT screen and can be popped also.

    import SwiftUI
        struct DetailScreen: View {
            var body: some View {
                VStack {
                NavigationLink(destination: WorkoutDetail(workout: workout)) {
  WorkoutRow(workout: workout)
}
            }
        }

Solution

  • NavigationStack($path) {
        HomeScreenControllerView(path: $path)
            .navigationDestination(...) {
                DetailView(...)
            }
    
    }
    ...
    struct HomeScreenControllerView: UIViewControllerRepresentable {
        @Binding var path: ...
        func makeUIViewController(...) {
            HomeScreenController()
        }
    
        func updateUIViewController(...) {
            viewController.onTap = {
                path = ...
            }
        }
    ...
    var onTap: (() -> Void)?
    
    @objc func buttonAction(sender: UIButton!) {
        onTap?()
     }