RxMvvM Back Navigation with SceneCoordinator

Hello, I am refactoring a pet project of mine to adopt this Rx MVVM architecture and so far everything thing is looking good.

There is only one problem, after presenting a new ViewController using a push coordinator transition, I need to override back button’s action to trigger coordinator pop.

  func presentDetails(of character: Character) -> Observable<Void> {
         let viewModel = CharacterDetailsViewModel(
             character: character,
             coordinator: coordinator
         )
         let nextScene = Scene.characterDetails(viewModel)
         return coordinator.transition(to: nextScene, type: .push)
 }

In the presented ViewController:

 func setupNavigationBackAction() {
        self.navigationItem.hidesBackButton = true
        var customBackButton = UIBarButtonItem(title: "Back", style: .done,
                                               target: nil, action: nil)
        customBackButton.rx.action = viewModel.backAction()
        self.navigationItem.leftBarButtonItem = customBackButton
}

If I do not do so, next time I would try to present something after popping the last presented view controller the app
will crash, because the app coordinator thinks it’s still in the last already disposed view controller.

I’m not happy with the way I “solved” it. Please, could you elaborate more about that? Also, I think it would be great if the book could provide an example of push transition and how to handle the subsequent popToViewController, all the examples cover only “.modal” transition, where you can explicitly pass the backAction for expected buttons( Having 100% control). That’s different when the navigationController have a system button that can do the pop without going through the coordinator.

Anyhow, I would like to thank you for the fantastic book! =)

If you could check the repo, there is a branch with this refactoring to RX MVVM → GitHub - thiagolioy/marvelapp at rxmvvm

This project is a sort of go-to project for me. Every time I would like to try something new, different architectures and so on. There is a lot to be improved; many things should have a better way to address using RxSwift. I still think that I’ve learned the rxTools but still need to make the mind shift, it I’d be amazing if you could point out some of them.

Best

1 Like

You are right that in the provided sample, things have to be manual. I typically solve it by having my view controllers derive from a common base class which does exactly this – trigger a pop on back action to make sure the SceneCoordinator stays up to date with the current view controller.

Another option to handle this would be to install the SceneCoordinator as a forwarding UINavigationControllerDelegate so it gets to know about frontmost VC transitions. I think the RxSwift DelegateProxy base pattern could be used there. I haven’t experimented with this approach yet, but I think this would be the best avenue to improve the pattern.

3 Likes