'How to fix problem with opening ViewController by action from Coordinator in Swift?
I'm trying to open another controller by tapping on the cell of my tableView. I'm coding with MVVM and Coordinator pattern.
In the beginning we see this screen - it is declarated in the method 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
}
Later, my goal is to open all list of countries of the continent, but now l just need to open empty ViewController by tap on the cell (ex. Africa or Antarctica). Here is my methods for it, but they don't work.
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)
}
Thank you so much!
Solution 1:[1]
The following works as expected. What are you doing differently?
@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
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Daniel T. |