I've introduced ViewModels into my latest iOS app but I'm getting stuck at a few places. Was wondering if anyone here could send me in the right direction.
Basically, How/Where should navigation and error dialogs be handled.
For example, currently I have a registration process that consists of a RegistrationViewController and a RegistrationViewModel. When the register button is tapped in the UI a register method is called on the RegistrationViewModel. i.e. viewModel.register() from the controller
Question 1: How should navigation get handled? After the registration call to the web service successfully completes the app should navigate to one of a number of screens depending on some business logic. Currently I handle this in the ViewModel by calling into a navigation manager class. Navigator.goToSuccessScreen(). Is this acceptable? I get the feeling that this should rather be handled inside the controller rather than through the ViewModel, but then all the business logic to determine where to navigate to will be done in the view controller.
Question 2: How to show a error dialog? Lets say that the registration call above failed. And the UI needs to show a UIAlertView to the user. Would it be OK to call Navigator.displayError("some or other error message")? Or should, once again, be a way to route this back to the controller to show the message itself?
MVVM (Model View ViewModel) is a design pattern, which has been widely used as more event-driven apps have started emerging. A few years back, if anyone built a product, it has probably been built using MVC (Model View Controller). In recent times, the MVC architecture has lost its place as the default design pattern.
KEY DIFFERENCE In MVC, controller is the entry point to the Application, while in MVVM, the view is the entry point to the Application. MVC Model component can be tested separately from the user, while MVVM is easy for separate unit testing, and code is event-driven.
Whenever we start building a new application, this question always comes in our mind, which architecture pattern to choose for our new project. The most used architectural pattern in iOS is MVC. Most of the developers used the MVC pattern for their projects.
You can handle it by using route enum and make it observable in ViewModel:
enum MoviesListViewModelRoute {
case initial
case showMovieDetail(title: String, overview: String, posterPlaceholderImage: Data?, posterPath: String?)
}
final class DefaultMoviesListViewModel: MoviesListViewModel {
// MARK: - OUTPUT
let route: Observable<MoviesListViewModelRoute> = Observable(.initial)
...
func didSelect(item: MoviesListItemViewModel) {
route.value = .showMovieDetail(title: item.title,
overview: item.overview,
posterPlaceholderImage: item.posterImage.value,
posterPath: item.posterPath)
}
Observe route value from View(viewController) and present it when the value changes:
final class MoviesListViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
bind(to: viewModel)
viewModel.viewDidLoad()
}
private func bind(to viewModel: MoviesListViewModel) {
viewModel.route.observe(on: self) { [weak self] in
self?.handle($0)
}
}
}
extension MoviesListViewController {
func handle(_ route: MoviesListViewModelRoute) {
switch route {
case .initial: break
case .showMovieDetail(let title, let overview, let posterPlaceholderImage, let posterPath):
let vc = moviesListViewControllersFactory.makeMoviesDetailsViewController(title: title,
overview: overview,
posterPlaceholderImage: posterPlaceholderImage,
posterPath: posterPath)
navigationController?.pushViewController(vc, animated: true)
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With