как перейти от swiftui к viewcontroller с использованием существующего контроллера навигации

#ios #swift #swiftui #uikit

#iOS #swift #swiftui #uikit

Вопрос:

у меня есть контроллер навигации, который переходит к контроллеру представления, который переходит к uihostingcontroller. Как бы мне перейти к другому контроллеру представления из 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()
    }
 

в контроллере предварительного просмотра видео

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

в 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: {})

                
}
}
 

Как мне перейти от действия просмотра кнопки swiftui к новому контроллеру представления с использованием существующего стека навигации

Комментарии:

1. SwiftUI не работает с UINavigationController, поэтому вам необходимо продолжать использовать UIKit для навигации в таком сценарии.

2. как бы я это сделал с помощью кнопки в swiftui. я внес правку в код. допустим, у меня там есть кнопка, как бы вы это сделали из ее действия

Ответ №1:

Я бы ввел UINavigationController в стек SwiftUI значения среды

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

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

затем в делегате представления таблицы введите его

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

и теперь FilmOverviewView мы можем это использовать

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

Обновление: обновлен пользовательский контроллер хостинга

 class UIHostingControllerCustom<V: View>: UIHostingController<V> {
    override func viewWillAppear(_ animated: Bool) { 
        navigationController?.setNavigationBarHidden(true, animated: false)
    }
}
 

Комментарии:

1. пусть контроллер = UIHostingControllerCustom(rootView: FilmOverviewView(обзор: TransHumanOverview()).environment(.NavigationController, self.NavigationController)) в табличном представлении выбрасывает Не удается преобразовать значение типа ‘some View’ в ожидаемый аргумент типа ‘FilmOverviewView’

2. Вам необходимо исправить обобщения в вашем пользовательском UIHostingControllerCustom классе.

3. класс UIHostingControllerCustom:UIHostingController<FilmOverviewView>{ переопределить функцию viewWillAppear(_ animated: Bool) { NavigationController?.setNavigationBarHidden(true, animated: false) } } Что мне нужно изменить здесь