如何通过协调员在 Swift 中的操作解决打开 ViewController 的问题?

How to fix problem with opening ViewController by action from Coordinator in Swift?

我正在尝试通过点击 tableView 的单元格来打开另一个控制器。我正在使用 MVVM 和协调器模式进行编码。

一开始我们看到这个屏幕 - 它在方法 start() 中声明

let service = Service()
private(set) weak var navigationController: UINavigationController?

func start() -> UINavigationController {
    let vm = ContinentsViewModel(service: service)
    let vc = ContinentsViewController(viewModel: vm)
    let navigationController = UINavigationController()
    self.navigationController = navigationController
    navigationController.setViewControllers([vc], animated: false)
    bindContinentsViewModel(viewModel: vm)
    return navigationController
}

稍后,我的目标是打开该大陆的所有国家/地区列表,但现在我只需要通过点击单元格(例如非​​洲或南极洲)打开空白 ViewController。这是我的方法,但它们不起作用。

private func showCountries() {
    let vc = ViewController()
    navigationController?.pushViewController(vc, animated: true)
}

private func bindContinentsViewModel(viewModel: ContinentsViewModel) {
    viewModel
        .flow
        .bind { [weak self] flow in
            switch flow {
            case .onContinentTap:
                self?.showCountries() // don't work
              //  print("show \(continent)") // work - continent is a param of .onContinentTap, which prints an geo-id of the continent, just if you need to know.
            }
        }
        .disposed(by: viewModel.bag)
}

非常感谢!

以下按预期工作。你有什么不同之处?

@main
final class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?
    var viewModel: ViewModel?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        viewModel = ViewModel()
        let controller = viewModel?.start()

        window = UIWindow(frame: UIScreen.main.bounds)
        window?.rootViewController = controller
        window?.makeKeyAndVisible()

        return true
    }
}

final class ViewModel {
    private(set) weak var navigationController: UINavigationController?

    func start() -> UINavigationController {
        let vm = ContinentsViewModel()
        let vc = ContinentsViewController(viewModel: vm)
        let navigationController = UINavigationController()
        self.navigationController = navigationController
        navigationController.setViewControllers([vc], animated: false)
        bindContinentsViewModel(viewModel: vm)
        return navigationController
    }

    private func showCountries() {
        let vc = UIViewController()
        vc.view.backgroundColor = .blue
        navigationController?.pushViewController(vc, animated: true)
    }

    private func bindContinentsViewModel(viewModel: ContinentsViewModel) {
        viewModel.flow
            .bind { [weak self] flow in
                switch flow {
                case .onContinentTap:
                    self?.showCountries()
                }
            }
            .disposed(by: viewModel.bag)
    }
}

final class ContinentsViewModel {
    enum Flow {
        case onContinentTap
    }
    let flow: Observable<Flow>
    let bag = DisposeBag()

    init() {
        flow = .just(.onContinentTap)
            .delay(.seconds(3), scheduler: MainScheduler.instance)
    }
}

final class ContinentsViewController: UIViewController {
    var viewModel: ContinentsViewModel
    init(viewModel: ContinentsViewModel) {
        self.viewModel = viewModel
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .red
    }
}