UIViewController: Fighting the monster | Andrei Raifura | CodeWay 2015

Preview:

Citation preview

Andrei Raifura iOS Department Manager, YOPESO

#CodeWăy

UIViewController: Fighting the monster

Overview

• The “monster” problem

• A practical solution

• View Controllers from historical perspective

Historical approach

Historical approach

Historical approach

Meet UIViewController

• Contains the View

• Manages the View

• Plays well with Interface Builder

• Defines a screen

• Conforms to MVC

Conceptual MVC

Model View

Controller

UpdateUpdate

User ActionNotify

ViewController’s MVC

Model ViewControllerView

Update

Notify

Meet UIViewController

The problem

Things changed

ViewController is the same (almost)

Model ViewControllerView

Update

Notify

ViewController’s Responsibilities

• View layout

• View management code

• Navigation logic

• View setup

• Core Data and NSFetchedResultsController code

• Delegate methods

• Other “decision making” code

View setup

@interface FMViewController () @property (weak, nonatomic) IBOutlet UITextField *usernameTextField; @property (weak, nonatomic) IBOutlet UITextField *passwordTextField; @property (weak, nonatomic) IBOutlet UIView *feedbackView; @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;

@end

@implementation FMViewController

View setup

- (void)viewDidLoad { [super viewDidLoad]; self.myButton.titleLabel.font = myCustomFont; UIImage *stretchableImage = [self.myButton setBackgroundImage:stretchableImage forControlState:UIControlStateNormal]; }

ViewController’s Responsibilities

• View layout

• View management code

• Navigation logic

• View setup

• Core Data and NSFetchedResultsController code

• Delegate methods

• Other “decision making” code

View layout

- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.myLabel.frame = /* ... */ self.myButton.frame = /* ... */ }

View layout

ViewController’s Responsibilities

• View layout

• View management code

• Navigation logic

• View setup

• Core Data and NSFetchedResultsController code

• Delegate methods

• Other “decision making” code

ViewController’s Responsibilities

• View layout

• View management code

• Navigation logic

• View setup

• Core Data and NSFetchedResultsController code

• Delegate methods

• Other “decision making” code

Navigation logic

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { id item = [self itemAtIndexPath:indexPath]; DetailsViewController *detailsVC = [[DetailsViewController alloc] initWithItem:item]; [self.navigationController pushViewController:detailsVC animated:YES]; }

ViewController’s Responsibilities

• View layout

• View management code

• Navigation logic

• View setup

• Core Data and NSFetchedResultsController code

• Delegate methods

• Other “decision making” code

Core Data code

• View layout

• View management code

• Navigation logic

• View setup

• Core Data and NSFetchedResultsController code

• Delegate methods

• Other “decision making” code

ViewController’s Responsibilities

• View layout

• View management code

• Navigation logic

• View setup

• Core Data and NSFetchedResultsController code

• Delegate methods

• Other “decision making” code

ViewController’s Responsibilities

• View layout

• View management code

• Navigation logic

• View setup

• Core Data and NSFetchedResultsController code

• Delegate methods

• Other “decision making” code

Decision making code

DetailsViewController *detailsVC = /* ... */; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { // display details in the split view controller's // details pane } else { // push details to the current navigation controller }

ViewController’s Responsibilities

• View layout

• View management code

• Navigation logic

• View setup

• Core Data and NSFetchedResultsController code

• Delegate methods

• Other “decision making” code

iOS Architecture

Looking into a View Controller

Looking for a solution

ViewController’s Responsibilities

• View layout

• View management code

• Navigation logic

• View setup

• Core Data and NSFetchedResultsController code

• Delegate methods

• Other “decision making” code

ViewController’s Responsibilities

• View layout

• View management code

• Navigation logic

• View setup

• Core Data and NSFetchedResultsController code

• Delegate methods

• Other “decision making” code

Demo

Reduced Responsibilities

• View layout

• View management code

• View setup

View Controller issues

• Cannot be tested (using unit tests)

• Requires changes when the UI is changed

ViewController’s MVC

Model ViewControllerView

Update

Notify

ViewController’s MVC

ViewControllerView

ViewController’s MVC

ViewController ViewUpdate

User Action

Demo

• Use View Models to encapsulate the information the view displays

• Put the IBOutlets in the private interface

• Create classes for views

• Use XIBs to define your layout

• Use a delegate to communicate asynchronous events from the view

• View keeps the datasources

Separate View from View Controller

• Testable View Controllers

• Ability to change the View without touching the View Controller

• More granular code

• It plays well with MVVM and VIPER concepts

Advantages

• Cannot use storyboards

• May lead to class explosion

• Requires some glue code

Disadvantages

One more thing?

Summary

• The “monster” problem

• A practical solution

• View Controllers from historical perspective

Questions?

Contacts

Raifura Andrei iOS Department Manager, YOPESO

andrei.raifura@yopeso.com

thelvis4@gmail.com

#CodeWăy