Changing UIViewController but keeping the behavior
Hello everyone this year I’ve learned a lot stuff like code review, testing, viewcode and more. This is probably my last post this year and I decided to talk about something very interesting that I saw on my last project.
You probably already had to change some UI of any project maybe just a few labels or every single view on it which can be very tricky. And if there’s a way that we can build a new UI from scratch and still be compatible with our previous one.
Our challenge was to build a framework that can be easily customized with new UI’s but it needs to keep the logic untouched, when I said new UI I mean an entirely new UIViewController
.
How can we create an architecture that will be able to handle that? e.g. how we can receive a custom UIViewController instantiated by a storyboard, viewcoded or black magic and still authenticate our user?
To achieve this we need to split our logic into separated files with it owns responsibilities and keep their dependencies in mind e.g. a LoginViewController
should have a username
, password
and a login
method.
First, we need to take out the login
responsibility and move it to another class that will actually do the authentication process. This removes the responsibility from our ViewController making it decoupled to our authenticate logic.
Let’s create a protocol that will do that:
Username
and password
are dependencies from our UIViewController. We need these properties to show something on UI. Your dependencies can be anything like a User
object or array for example.
Now we need to create a class that will have these properties and actions (username
, password
and a LoginActions's
delegate)
This will be our base class any custom Login’s UI should inherit from LoginViewController
.
Let’s create a new UIViewController
called LoginView1
:
And another one called LoginView2
:
Notice that neither of our LoginView actually authenticate our user, they receive a boolean value that indicates that if the user was authenticated or not. The authentication process will be done by our delegate that can be implemented in many different ways. Here we are going to create a coordinator
that will implement our LoginActions
.
Our coordinator start method returns a LoginViewController
which can be created by a storyboard file, viewcoded or injected in another way. It will be responsible for authenticate our user in this example, but fell free to remove this responsibility from it and put in another file.
Removing responsibilities from our UIViewController
make it highly customizable, decouple to any kind of logic, more testable, readable and cleaner. Just don’t forget to keep the dependencies in a base class, they will be needed in any implementation.
Ps: If you like this post, share it on twitter, recommend it on medium, or both =). This really helps me to reach more people. Thanks a lot.