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

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.

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.

How to construct clean presentation layer on iOS app

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.

Storyboard design pattern (to share or not to share)

This is probably largely preferential but I'd like to know if there are any reasons to decide one way or another on this.
When designing with storyboards you invariably end up with a number of view controllers. I'm looking at the overhead of a strict MVC approach where each controller is implemented in its own UIViewController subclass with corresponding UIView subclass (and even view model class for MVVM), and that seems to get out of hand quickly – it takes no time to add dozens of files to the project (many with little function). An alternative approach would be to link all the views to a common controller representative of all of the storyboard functionality.
My inclination is that if you don't have substantial controller code for any individual view controller, then the combination of all of them into one shouldn't be of harm to the readability of the code (and may enhance it over adding a large number of source files). On the other hand, if you have significant functionality to implement for any particular view controller, then it should be encapsulated within it's own controller.
In most situations I'd build all controllers to be as reusable as possible (encapsulated in their own custom UIViewController subclasses). Storyboards put this in an interesting light though since they seem to be geared towards sequences of views that typically have few entry points.
Your thinking is correct
If you don't have much functionality in each VC (ViewController) them combine all your code into one VC. The only drawback to this approach is that you won't be able to implement view specific code and every view where you will use this common VC will execute the same code whether its needed there or not. e.g. code in viewWillAppear etc.
Similarly if you have a lot of functionality for a particular view then its better to put it under its own VC
This is just a suggestion, if you need to use some common code logic between multiple VCs then instead of doing copy and paste in each VC of the same code, make it into a method of type Category and then call it where ever its needed. So change the code only at 1 place.
More VCs doesn't necessarily mean bad design. In my opinion its easier to maintain that way. My two cents. :-)
Each scene in your storyboard should have its own UIViewController subclass. Even doing it like this it's way too easy to get huge unmaintainable view controllers (MVC = Massive View Controller). Putting all the code for multiple scenes in the same view controller would create even bigger ones and also violate the Single Responsibility Principle. Each class should do only a single thing.
That also means you shouldn't duplicate the common functionality into all your UIViewController subclasses. Then they again would do multiple things - the common stuff and their actual purpose. Instead you can put your common code in other controller objects (which are not descendants of UIViewController) and use them in your view controllers.
Depending on the usecase a common base class would work as well, but it's always preferable to use composition instead of inheritance.
Another nice thing about other controller objects is that you also can add them directly in Interface Builder and connect actions and outlets to them. Your main view controller class often doesn't even have to know they exist.

Is it appropriate to have view controllers that have multiple views?

I have a quick question in regards to my app that I am developing for school. In my app we have 5 unique games that the user can play. However, each game has 2 modes, normal and hard. What is the best way about going to do this. Currently I have my first game as two separate view controllers and are called based on the difficulty that is wanted(one called normal_cstars and hard_cstars). I am wondering if this is efficient because each view controller has a .h, .m, and a .xib. Is it possible to have a view controller that has two separate views and how would you go about accomplishing this.
Thanks,
Ryan Wong
Of course. You can pick which one of the two views you display inside your viewcontrollers. Just send self.view in the view controller to be the view you'd like to use.
One way to architect this is to have two separate view classes that share the same controls. The controls are all handled by the view controller while the views each draw their own layout.
And don't be worried about sharing subviews among the two main views -- or you can keep your two view controllers, and just have shared classes that make up the views and controls of each view controller's presentation. Just because you have two view controllers doesn't mean you have to have redundancy code. Split things out into separate classes, from your animated views to your controls.
There are a lot of other possibilities. Look at some of Apple's samples to see how multiple view controllers are used.
Do you really think that you need two separate views? (I am not sure about your game though)
Since game modes are Model specific, a model with behaviour "Normal" or "Hard" will actually render the game in a view.
If near future, if you want to implement a mode "Easy" then you end up with another view controller and might encounter code redundancy.
Solution I would think:
Create a inheritance over composition pattern for your model objects.
A view controller will be much more generic and tells view to render based on the mode
Now the base class of the model will implement generic methods and since the model has mode as composition, the view will render the game objects based on it.
Advantages? - well we have not violated the Open-Closed Principle.
And again there are various design patterns out there to achieve this. Its up to you to decide which suits the best for the requirements.

iOS - dealing with large and growing UIViewController classes

I have a UIViewController that over time has had a lot of delegate events added to it which has made the controller class quite large. The UIViewController class contains quite a few view-management methods that are called from the event-delegate methods to manage the UIView that the controller is managing.
I am now adding further UIActionSheet delegate events to the class. My controller class is getting large and I'm thinking that I should break out the UIActionSheet delegate events and place them in a separate delegate class. This separate delegate class will then have to call back into the view controller class to get the view controller to adjust the view accordingly, using the view-management methods within the view controller. (The view controller accesses a separate model object that the view is representing).
I can see pros and cons to adopting this break-out approach. It feels wrong to be adding more and more delegate events to the controller, but creating separate classes for different categories of events that then need to call back into the controller also seems to introduce an unnecessary layer of complexity and obfuscation. The large controller class is 'simple and straightforward' but feels wrong, whilst using numerous different delegate classes will be somewhat more complex and involved but will result in smaller classes.
Can anyone provide some words of wisdom on this topic, and perhaps point me towards some iOS-specific reading on the matter?
Many thanks.
My approach to this matter is:
Make it work
Make it cleaver
Back to 1.
(Or 1 and 2 both in same turn if you are experienced in a field)
So if code works app looks good but you find that ups some class has 100 methods in it so try different design patters (if you haven`t already) and use those cleaver ideas to make code separation into different classes, delegates, encapsulate them if necessary et.
http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/CocoaDesignPatterns.html
Just in case link to Cocoa Design pattern suggestions and i am from time to time looking into Pro objective c design patterns for ios. Might be not the best book out there but it is based on "Gang of four" design patterns book in ios context.
Hope this helps at least somehow,
Cheers
In the end I created quite a few additional classes for dealing with specific UIActionSheet instances. I created a base class and then subclassed this for each UIActionSheet requirement within the main controller.
The end result looks tidy, and doesn't add too much complexity.

Resources