How to construct clean presentation layer on iOS app - ios

I make an app with DDD
I’m able to make clean domain layer which domains are clearly separated from other layers.
But Controllers on presentations layer are mess.
ViewControllers have multiple responsibilities
even though domain is successfully separated.
A ViewController tend to have multiple responsibilities such as
Navigation
Deleate
Analytics
Animation
Access on multiple domains etc.
There often are many ViewControllers with slightly different functions.
If trying to make those with template method, hierarchy of ViewControllers get too complicated.
If trying to make those without template method, there will be many ViewControllers which shares some functions. This way is vulnerable to change.
What are some best practices?
How to construct clean presentation layer on iOS app?

In practice, Cocoa MVC often leads to massive-view-controller problem. The solution is to move to a more fine grained architecture like MVP or VIPER.
In MVP on iOS the View is represented by UIViewController (or bare UIView), thus UIViewController is no more loaded with business logic.
VIPER has even more layers and also solves UI navigation task.

Related

When following MVC design pattern what code should be in the UIViewController class file? - Swift4

I'm trying to understand how to properly implement MVC in swift. Heres my scenario:
I have a signup page with 9 UITextFields, and they're all being made programmatically, and therefore being anchored to the view programmatically. As you can imagine this would be a lot of repetitive code to have in the SignupViewController class file.
Is the convention when following MVC to keep the setup of these text fields in the SignupViewController file, or are you supposed to have a separate file such as SignupView that contains all the text field setup code?
Even though UIViewController has the word "controller" in it, I believe the majority of iOS devs these days assign the UIViewController to the "View" side of MVC. The UIViewController is chiefly specific to a particular view only, plus may manage its subviews as well (until this gets too messy and a container view is added to allow for a nested UIViewController).
In MVC on iOS, the view controller can easily become polluted with business logic, model management, etc... which is why many people jokingly refer to "MVC" in iOS as "Massive View Controller". To combat this, consider using an MVVM architecture instead, which not only keeps the VCs small, but also moves the business logic out to a separate "sidecar" coupled to that ViewController, called a ViewModel. This allows the business logic to be unit tested without any UI involved, making testing much more reliable and easier to read and maintain. With that said, the creation of these 9 controls would still belong in the ViewController.
As for programmatically adding UITextFields to your view vs viewController, if this is to be done just for this single scene, then I'd stick it into the viewController. If you expect to want to reuse the set of them in other scenes, then making a custom view or control containing them would be better, like is typically done for custom cells of a table.
Finally, consider simply using a Nib or Storyboard to layout your scene. Apple has provided so much power to layout and maintain scenes via nibs and storyboards that you're really missing out to go the programmatic route. I find it very rare that I side with programmatic approach. The auto-layout warnings in InterfaceBuilder alone are worth gold to me, and as Apple continues to raise the bar and change layout rules, I can't imagine trying to keep up programmatically when I can't afford to test every device and iOS version combination. And yes, it's possible to do MVVM with dependency injection and storyboards. I do it daily.
Answer to your question is that it has nothing to do with MVC .
AS iOS/Mac developers, we use Interface builder and auto_layout to achieve most UI #IBOUtlet/ #IBAction. This is the V side of MVC.
Typically, If you have data, database, json or whatever formats, you need to model them and handle logics. That'M of MVC.
The C(Controller) side of MVC is a kind of glue between M and V. In most cases of mobile , you can think Controllers are all C you need.
So controller class is the only portion you need to put code to simplify everything.
In your case, 9 UITextfields should be ideally put into V side job. Please don't write code for them unless there is no better way to do.
I don't agree with above statement about using Interface Builder... I prefer to write most of my views in code and also set the anchors that way as well.
to minimize the file you can create an extension of the ViewController in a separate file to contain all of this code.
so for SignupViewController you would create a new file called SignupViewController+SetupUI.swift.
import UIKit
extension SignupViewController {
// add your setup methods here
// as just an FYI you can call the methods you create from your
// SignupViewController file just like you would any other method.
}
you can read more about extensions here.
After reading about good practices to write maintainable and readable code you should do the whole design in interface builder. If you get good understanding of constraints you don't need to write any code to setup design in your view controller. The ViewController.swift file should not be used to fetch-handle data or to setup the UI. It should just be responsible to display and update values which are fetched and get handled in a separate ViewControllerDatasource.swift file. So to sum up, view controller does not have any logic implemented it just handles the show data and the design updates(not setup). I hope i helped you with your question.

Storyboard in Xcode

I've been working with Xcode for a while, and what I'm doing works, but I can't image that it is the best way to do it. When I want to transition between scenes in Xcode, I create a segue between UIViewControllers in the main storyboard. This is a picture of a storyboard in one of my apps.
By looking at the picture, you can probably understand why I'm curious about whether or not what I'm doing is bad practice. What should I be doing to transition between scenes, or what do most people do to transition between scenes? Thanks for the help!
This is not easy to answer, but I will give you some context:
Storyboards can be a nice visual way to remove push/present code from the view controllers and make it clear what is happening (vs code).
Having UIViewControllers handle navigation is not considered best practices (at least in many larger projects/enterprises). This is why patterns like VIPER (among other reasons, and yes VIPER can be overkill).
In your case the relationship is not clear, many things also go back and forth. Now it might be possible you can lay them out better, and perhaps the containment or relationships can be tweaked.
Here's some advice I can give. Try to make view controllers as dumb as possible about opening other view controllers, both the what and how - they ideally should just indicate to some controller/mediator/manager they wish to "do" something. It makes maintenance and refactoring a lot easier, especially adding a new feature later that might change how navigation works, such as adding on boarding into the app.
Long story short, storyboards are not bad, however many enterprise and large projects do not use them both due to the difficulty in version control with multiple developers (using shallow storyboards with NIBs can mitigate this, you do lose some of the Segue), and because you can tend to grow overly complex view controllers. Its great for personal, smaller apps... as complexity grows, value proposition becomes thinner.

How to handle huge view controllers so code is not dirty?

I'm having a problem with the app I am developing right now : one of my UIViewControllers is huge ( around 3000 lines ).
For now, I created extensions of this view controller to handle delegate methods in order to "split" this controller. For instance, I have my main view controller called XYZMainViewController and as this controller is the delegate of a UITextField, I created an extension XYZMainViewControllerTextFieldDelegateExtension.swift in which I manage UITextFieldDelegate methods.
It's still pretty dirty to do that this way. I'm wondering what would be a good practice to handle huge controllers like this one.
did you consider to design your app using MVVM (model view view model) the idea of MVVM is to avoid huge controllers. There are a lot of user guides out there which explain how to use MVVM in your IOS app. I was facing the same situation half a year ago and then i adopt MVVM in my app and i am very happy with it since my controllers are not huge, i can reuse code easily in my app and also it's much more easy to create unit tests.
Please follow this guide which explain what is MVVM and how to use
ithttps://www.raywenderlich.com/74106/mvvm-tutorial-with-reactivecocoa-part-1
https://www.raywenderlich.com/74131/mvvm-tutorial-with-reactivecocoa-part-2
3000 lines is hmmmm hugeeeeee.
You have performed huge numbers of tasks in your controller. Controllers are supposed to control views.In my opinion(the way i create my iOS app structure) controller is suppose to perform view control,passing data from models to view(more specifically from classes which manipulates data).
"Separate of concerns" is important here. Don't implement your business logic inside controllers. There should be a separate module which do all of your business logic. How to manipulate models and complete a functionality. Then this class is used by controller to perform view updates.
No matter what type os view you have designed ,its controller can't be of 3000 lines. Delegation is not a problem. Controller is a good place to do delegation. Inside those delegate methods ,to perform some business is not the work of controller. There are some design patterns for IOS apps like MVC, MVVM.
But still you have to use "these design patterns efficiently. move the common functionality in one place etc. Implementation of business logic. Manipulation of models. Communication with DataBase.
Thanks.

Two view controllers, one view?

As I was working on a login/register view for my app I came across this predicament. Login and register are two different functions; therefore they should be in two different view controllers. However, the way I designed the view makes it overly complicated to have two views because the animations for the transition between the two functions are themselves complicated. How can I build this part of the app while adhering to the MVC guidelines?
Apple defines a view controller as one "screenful" of information. If you think that login and signup can co-exist as the same "screenful" of information, I don't think it's worth trying to separate them. More importantly, you can separate all of the other logic to clean up this class. The networking code should be in some kind of request client, setting username/password should be in an account manager, etc.
You can easily achieve this and even go further, add some cool transition animation between the two VC by using Container View. You can easily swap two different VC in this container. I usually do that to replace UISplitView for iPad due to its problems when implementing in i.e. UITabBarController. All in all, using container view is a good way to tidy the code between two different VCs when the app requires replacing these, quite often and avoiding the solution of a s.c. Massive-View-Controller :)
You can start with this tutorial, it includes a github repository and describes all practices with Container View.
link for tutorial

Multi-layered child viewcontrollers where delegation is becoming a nightmare - how should they communicate with each other?

This is a serious problem for me right now. Working on a code base with multi-layered children viewcontrollers about 4-5 layers deep - this is a tablet app with a very high degree of decoupling between viewcontrollers. The 5th layer child viewcontroller wants to send a message to the top level viewcontroller to show a modal. The 4th layer and 3rd layer have different messages as well so basically now I have like 4 protocols and its getting pretty complicated to send messages from such child viewcontrollers nested deep within to an ancestor viewcontroller. Is there an easier way to do this?
We thought about using NSNotification but not particularly fond of it because of its difficulty in debugging it and subscription not being a clear dependency within our control. We also thought about using a singleton but statics and singletons are evil (right?) and cause problems around state and concurrency.
Any help is appreciated. Also I realize I realize this is a slightly open ended design based question but it has a very specific use case (like the one described above).
Is an interesting question, but I guess we need few hints, such as a scheme. The first thought is why you need to add nested child? couldn't you manage using a simple stack and a single Container VC? It seems to be not correct how you manage your VCs. If they need to be notified about changes in the model, it should be only the visible to catch them, in the viewWill/Did/appear of the others you can ask fresh data again. If you need to inform each VC about their states, I think you should modify your hierarchy.
I imagine a Container VC with a stack or a set of VCs and visible VC propery. This Container will manage the exchange of info. As rdelmar said, it seems a really high degrees of coupling. You should rethink in way that sees communication only between container and visible VC, the others can refresh their data while they appear.

Resources