Rxswift + Mvvm + Coordinator Pattern, How to Wait for Coordinator Result Sequentially

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

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

How do i use coordinators with a UIITabBarController?

My Coordinator structure is a different than yours, but it might help you. In my case, the Coordinator protocol has a rootViewController property which points to that Coordinator's ViewController.

My AppCoordinator then persists a TabCoordinator, which looks somewhat like this: (In the real code, the persisted coordinators are NavigationCoordinators, which are special Coordinators that hold NavigationControllers. In this example I just added the ViewControllers and removed memory management stuff to make it easier to understand.)

final class TabCoordinator: NSObject, Coordinator {

var rootViewController: UIViewController {
return tabController
}

let tabController: UITabBarController

let homeCoordinator: HomeCoordinator
let historyCoordinator: HistoryCoordinator
let profileCoordinator: ProfileCoordinator

var coordinators: [Coordinator] {
return [homeCoordinator, historyCoordinator, profileCoordinator]
}

init(client: HTTPClient, persistence: Persistence) {

tabController = UITabBarController()

homeCoordinator = HomeCoordinator(client: client, persistence: persistence)

historyCoordinator = HistoryCoordinator(client: client, persistence: persistence)

profileCoordinator = ProfileCoordinator(client: client, persistence: persistence)

var controllers: [UIViewController] = []

let homeViewController = homeCoordinator.rootViewController
homeViewController.tabBarItem = UITabBarItem(title: Localization.homeTab.string, image: Asset.iconMenuRecharge.image, selectedImage: Asset.iconMenuRechargeActivated.image)

let historyViewController = historyCoordinator.rootViewController
historyViewController.tabBarItem = UITabBarItem(title: Localization.walletTab.string, image: Asset.iconMenuWallet.image, selectedImage: Asset.iconMenuWalletActivated.image)

let profileViewController = profileCoordinator.rootViewController
profileViewController.tabBarItem = UITabBarItem(title: Localization.profileTab.string, image: Asset.iconMenuProfile.image, selectedImage: Asset.iconMenuProfileActivated.image)

super.init()

controllers.append(homeViewController)
controllers.append(historyViewController)
controllers.append(profileViewController)

tabController.viewControllers = controllers
tabController.tabBar.isTranslucent = false
tabController.delegate = self

}
}

So basically, your TabBarController is a TabCoordinator whose's rootViewController is a TabBarController. The TabCoordinator instantiates the relevant Coordinators and add their respective rootViewControllers to the tab.

Here's a basic implementation of the NavigationCoordinator:

class NavigationCoordinator: NSObject, Coordinator {    

public var navigationController: UINavigationController

public override init() {
self.navigationController = UINavigationController()
self.navigationController.view.backgroundColor = .white
super.init()
}

public var rootViewController: UIViewController {
return navigationController
}
}

And a basic version of a Coordinator:

public protocol Coordinator: class {    
var rootViewController: UIViewController { get }
}


Related Topics



Leave a reply



Submit