76
VIPER то, о чем все говорят, но никто не рассказывает

MBLTDev15: Egor Tolstoy, Rambler&Co

Embed Size (px)

Citation preview

VIPERто, о чем все говорят, но никто

не рассказывает

Автор

Егор Толстой

Ведущий iOS разработчик

Rambler&Co

Twitter: @igrekde

www.github.com/igrekde

CompositionViewController

@interface

@interface

[self updateContactsView];

CompositionViewController

@interface

[self updateContactsView];

CompositionViewController

- (void)saveMessageToDraft { // Crash }

CompositionViewController

- (void)sendMessage { // Crash }

CompositionViewController

@end

- (void)updateAddressBook { // Crash // Crash // Crash }

CompositionViewController

- (void)updateAddressBook { if (invalidContacts) { return; } }

@end

CompositionViewController

@end

CompositionViewController

@interface

CompositionViewController

Хотим 100% crash-free!Хотим быстро и качественно!

Хотим чистый код!Хотим модульность!

•Структура VIPER модуля

•Связь модулей

•Возможности использования VIPER

VIEW PRESENTER INTERACTOR

ROUTERE

E

VIEW PRESENTER INTERACTOR

ROUTERE

E

VIEW PRESENTER INTERACTOR

ROUTERE

E

VIEW PRESENTER INTERACTOR

ROUTERE

E

VIEW PRESENTER INTERACTOR

ROUTERE

E

VIEW PRESENTER INTERACTOR

ROUTERE

E

VIEW PRESENTER INTERACTOR

ROUTERE

E

VIEW PRESENTER INTERACTOR

ROUTERE

E

TABLEVIEW

CELLFACTORY

View Presenter Interactor Router

- (void)viewDidLoad { [super viewDidLoad]; }

[self setupBarWithTitle:@"#mbltdev"];

- (void)setupBarWithTitle:(NSString *)title { self.navigationItem.title = title; }

View Presenter Interactor Router

- (void)viewDidLoad { [super viewDidLoad]; }

[self setupBarWithTitle:@"#mbltdev"];

- (void)setupBarWithTitle:(NSString *)title { self.navigationItem.title = title; }

View Presenter Interactor Router

Lifecycle

[self setupBarWithTitle:@"#mbltdev"];

View Presenter Interactor Router

Lifecycle

- (void)setupBarWithTitle:(NSString *)title { self.navigationItem.title = title; }

Navbar Setup

View Presenter Interactor Router

Lifecycle

Navbar Setup

[self setupBarWithTitle:@"#mbltdev"];Handles events

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events

BOOL valid = [self.inputValidator validatePhoneNumber:phoneNumber];if (valid) {

} else {

}

[self processToNextScreen];

[self showErrorAlertView];

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events

if (valid) {

} else {

}

[self processToNextScreen];

[self showErrorAlertView];

BOOL valid = [self.inputValidator validatePhoneNumber:phoneNumber];

Data validation

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events

if (valid) {

} else {

}[self showErrorAlertView];

Data validation[self processToNextScreen];Module Routing

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events

if (valid) {

} else {

}

Data validation Module Routing

[self showErrorAlertView];Shows data

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows dataif (valid) {

} else {

}if-else

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows data

if-else

[rootSavingContext performBlock:^{ Message *message = [Message MR_findFirst]; }];

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows data

if-else[rootSavingContext performBlock:^{ Message *message = [Message MR_findFirst]; }];

Data storage

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows data

if-else Data storage

NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request]; [dataTask resume];

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows data

if-else Data storage

NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request]; [dataTask resume];

Networking

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows data

if-else Data storage

Networking

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { segue.destinationViewController.inputData = @"inputData"; }

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows data

if-else Data storage

Networking

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { segue.destinationViewController.inputData = @"inputData"; }

Segues

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows data

if-else Data storage

Networking

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { MyCell *cell = [tableView dequeueReusableCell]; [cell setupWithObject:cellObject]; }

Segues

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows data

if-else Data storage

Networking

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { MyCell *cell = [tableView dequeueReusableCell]; [cell setupWithObject:cellObject]; }

Segues

Table DataSource

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows data

if-else Data storage

Networking

- (void)panGestureRecognizerDidChangeState:(id)sender { CGPoint panPoint = [sender translationInView:self.view]; self.view.frame = CGRectMake(panPoint.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height); }

Segues

Table DataSource

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows data

if-else Data storage

Networking

- (void)panGestureRecognizerDidChangeState:(id)sender { CGPoint panPoint = [sender translationInView:self.view]; self.view.frame = CGRectMake(panPoint.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height); }

Simple gestures

Segues

Table DataSource

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows data

if-else Data storage

Networking

Simple gestures

if (panPoint.x > 100.0f) { }

[self showSideMenu];

Segues

Table DataSource

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows data

if-else Data storage

Networking

Simple gestures

if (panPoint.x > 100.0f) { }

[self showSideMenu];Side Menu

Segues

Table DataSource

View Presenter Interactor Router

Lifecycle

Navbar Setup

Handles events Data validation Module Routing

Shows data

if-else Data storage

Networking

Segues

Table DataSource

Simple gestures

Side Menuif (panPoint.x > 100.0f) { }Complex gestures

VIEW PRESENTER INTERACTOR

ROUTERE

E

VIEW PRESENTER INTERACTOR

ROUTER ESERVICE

SERVICE

SERVICE

E

Роутер должен роутить

VIEW PRESENTER INTERACTOR

ROUTER ESERVICE

SERVICE

SERVICE

E

ASSEMBLY

Экран=

Модуль

Экран=

Модуль

UIViewControllerUIView

UITabBarControllerDaemon

VIEW PRESENTER INTERACTOR

ROUTER ESERVICE

SERVICE

SERVICE

E

ASSEMBLY

VIEW PRESENTER INTERACTOR

ROUTER ESERVICE

SERVICE

SERVICE

E

ASSEMBLY

PRESENTER

INTERACTOR

VIEW

ROUTER

VIEW

PRESENTER

INTERACTOR

ROUTER

Модуль 1 Модуль 2

PRESENTER

INTERACTOR

VIEW

ROUTER

VIEW

PRESENTER

INTERACTOR

ROUTER

@"Module2Segue"

<TransitionHandler> <ModuleInput>

Модуль 1 Модуль 2

@implementation Router

[[self.transitionHandler openModuleUsingSegue:SegueIdentifier]         thenChainUsingBlock:^void(id<SomeModuleInput> moduleInput) {                 [moduleInput moduleConfigurationMethod];         }];

@end

PRESENTER

INTERACTOR

VIEW

ROUTER

VIEW

PRESENTER

INTERACTOR

ROUTER

Список контактов Карточка контакта

contactId

contact

MODULEVIEW

MODULEPRESENTER

MODULEINTERACTOR

MODULEROUTER <SUBMODULE2INPUT>

<SUBMODULE1INPUT>

<SUBMODULE3INPUT>

~ 99% Code Coverage

VIEW

TEST

pod 'MyApp/Core', '1.2.2'

pod 'MyApp/Modules/CalendarModule', '1.5'

pod 'MyApp/Modules/SettingsModule', '1.0.1'

pod 'SharedModules/Authorization', '2.3.4'

• VIPER увеличивает тестируемость приложения,• VIPER увеличивает модульность приложения,• VIPER делает нашу жизнь немного прекраснее.

One more thing...

❤VIPER

Open Source

• Рамблер.Конференции - приложение

• Generamba - генератор

• VIPER McFlurry - библиотека

• The Book of VIPER - сборник статей

https://github.com/rambler-ios

Дизайн: студия «Рамблер Инфографика»