Login screen implementation using MVVM + RxSwift
This article is dedicated to demonstrate modern approach to building sign-in/sign-up flows in iOS apps using MVVM architecture and RxSwift framework.
Our UI will be setup in storyboard and looks like this:
Just 2 plain text fields and single button.
To start off we need to define two important types for view controllers and view models, to keep our app architecture consistent from the beginning and to enforce code style for future features.
All ViewController
subclass objects in our app should conform to ControllerType
protocol and define concrete type of view model, implement create(_:)
and configure(with:)
functions. On other side all view model objects should conform to ViewModelProtocol
and define two associated types: Input
and Output
. This approach for view model design is described by Martin Moizard in his article RxSwift + MVVM: how to feed ViewModels.
After adopting these rules out view controller and view model setup will look like this:
Right now our LoginControllerViewModel
provides no functionality. Lets fix this! 😄
We need to define inputs and outputs for our view model. Our inputs will be:
- Password
- SignIn button tap
In their turn, outputs will be defined as:
- Observable of login results (
User
instances) - Observable of errors that may rise (invalid credentials, etc.)
Next iteration of LoginControllerViewModel
will have this structure:
In its turn LoginController
will need to define implementation of configure(with:)
function. It will have following structure:
This function just binds view model’s inputs and outputs to view controller.
For a completeness of out type system, we need to define few new types User
, Credentials
, LoginService
.
User
and Credentials
are plain data objects, declared like this (unnecessary details are omitted):
LoginService
is slightly more complex type. It’s dedicated to authenticate user. It’s going to be conforming to LoginServiceProtocol
protocol to enable Dependency Injection for testing purposes of view model layer. To omit authentication details we will just return an Observable<User>
.
Having everything in place we can inject LoginService
in LoginControllerViewModel
to enable authentication of user using it’s credentials.
Assembling of MVVM stack we will conduct in AppDelegate, but in real app you should look for more suitable places for this kind of task, for example — Coordinator.
With this approach our types have clearly defined interfaces, appropriate level of encapsulation, adopted Single Responsibility and Open/Closed principles.
You can find complete code of this project on GitHub.
Please leave any comments! All feedback is appreciated!
More where this came from
This story is published in Noteworthy, where thousands come every day to learn about the people & ideas shaping the products we love.
Follow our publication to see more stories featured by the Journal team.