2

i have a navigation controller which navigates to a view controller, which navigates to uihostingcontroller. How would i push to another view controller from swift ui

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        self.window = UIWindow(frame: windowScene.coordinateSpace.bounds)
        window?.windowScene = windowScene
        let navigationView = UINavigationController(rootViewController: PreviewViewVideoController())
        navigationView.isToolbarHidden = true
        self.window?.rootViewController = navigationView
        self.window?.makeKeyAndVisible()
    }

in preview video controller

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        switch cards[indexPath.row] {
        case .trans_human:
            let controller = UIHostingControllerCustom(rootView: FilmOverviewView(overview: TransHumanOverview()))
            self.navigationController?.pushViewController(controller, animated: true)
            controller.navigationItem.title = cards[indexPath.row].rawValue
}
}

in filmOverviewView

struct FilmOverviewView: View {
    var filmOverview: FilmOverview!
    var imageResource: String!
    
    init(overview: FilmOverview) {
        filmOverview = overview
        
    }

var body: some View {
    ScrollView(Axis.Set.vertical, showsIndicators: false) {
        VStack {
            Image(filmOverview.imageResource)
                .resizable()
                .frame(width: UIScreen.main.bounds.width,
                       height: UIScreen.main.bounds.height / 2)
                .overlay(StartButtonOverlay(), alignment: .bottom)
            Button(action: {})

                
}
}

How would i navigate from a swiftui button view action to a new view controller using existing navigation stack

2
  • SwiftUI does not work with UINavigationController, so you need to continue using UIKit to navigate in such scenario. Commented Dec 5, 2020 at 18:50
  • how would i do that from a button in swiftui. i made an edit on the code.let say i have a button there, how would u do that from its action Commented Dec 5, 2020 at 18:53

1 Answer 1

3

I would inject UINavigationController into SwiftUI stack via environment values

struct NavigationControllerKey: EnvironmentKey {
    static let defaultValue: UINavigationController? = nil
}

extension EnvironmentValues {
    var navigationController: NavigationControllerKey.Value {
        get {
            return self[NavigationControllerKey.self]
        }
        set {
            self[NavigationControllerKey.self] = newValue
        }
    }
}

then in table view delegate inject it

let controller = UIHostingControllerCustom(rootView: 
      FilmOverviewView(overview: TransHumanOverview()
         .environment(\.navigationController, self.navigationController))

and now in FilmOverviewView we can use it

struct FilmOverviewView: View {
   @Environment(\.navigationController) var navigationController
   // ... other code

   var body: some View {
       ScrollView(Axis.Set.vertical, showsIndicators: false) {
          VStack {
            // ... other code

            Button("Demo") {
               let controller = UIHostingControllerCustom(rootView: 
                  SomeOtherView()   // inject if needed again
                     .environment(\.navigationController, self.navigationController)))
               self.navigationController?.pushViewController(controller, animated: true)
            }
   }
}

Update: updated custom hosting controller

class UIHostingControllerCustom<V: View>: UIHostingController<V> {
    override func viewWillAppear(_ animated: Bool) { 
        navigationController?.setNavigationBarHidden(true, animated: false)
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

let controller = UIHostingControllerCustom(rootView: FilmOverviewView(overview: TransHumanOverview()).environment(\.navigationController, self.navigationController)) in table view is throwing Cannot convert value of type 'some View' to expected argument type 'FilmOverviewView'
You need to correct generics in your custom UIHostingControllerCustom class.
class UIHostingControllerCustom:UIHostingController<FilmOverviewView>{ override func viewWillAppear(_ animated: Bool) { navigationController?.setNavigationBarHidden(true, animated: false) } } What do i need to change here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.