ݺߣ

ݺߣShare a Scribd company logo
Реактивный VIPER
Дмитрий Котенко, «Туту.ру»
Реактивный VIPER
Дмитрий Котенко, «Туту.ру»
1
VIPER
Interactor Presenter View
Router
Показывает информацию
пользователю
и переадресует презентеру
действия пользователя
Управляет
вью-контроллером
Общается с сервером
и базой данных
Отвечает за переходы
между экранами
Entity
Entity
Entity
2
Обычный VIPER
Interactor Presenter View
Router
Entity
Entity
Entity
InteractorInput
InteractorOutput
ViewInputViewOutput
RouterInput
· output· output · view
· interactor
3
Презентер и вью
Presenter View
ViewInputViewOutput
· output· view
var button: UIButtonfunc onButtonTapped() {
interactor.loadNews()
} var output: NewsViewOutput!
@IBAction func buttonTapped() {
output.onButtonTapped()
}
func setNews(news: [String]) {
label.text = news.joined(“n”)
}
var view: NewsViewInput!
func newsLoaded(_ news: [String]) {
view.setNews(news)
}
4
Обычный VIPER
Interactor Presenter View
Router
Entity
Entity
Entity
InteractorInput
InteractorOutput
ViewInputViewOutput
RouterInput
· output· output · view
· interactor
5
Сигналы
Текст, набираемый в текстовом поле.
Положение курсора мыши
Значения ячеек в таблице
6
Сигналы в RxSwift
var scrollPosition: Observable<CGPoint> = ...
scrollPosition.subscribe(onNext: { point in
print("User scrolled to (point).")
})
7
Плюсы сигналов
var tableView: UITableView
1. Скролл-вью не знает ни про каких делегатов.
2. Никаких протоколов.
3. Сигнал можно переиспользовать
в нескольких местах.
tableView.delegate = self
extension OffersViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
processScrolling(scrollView.offset)
}
}
let scrollPosition = tableView.rx.contentOffset
scrollPosition.subscribe(onNext: { offset in
self.processScrolling(offset)
})
8
Реактивный ViewOutput
View
ViewInput
Presenter
InteractorOutput
· view
· interactor
ViewOutput
· output
func onButtonTapped() {
interactor.loadNews()
state = .loading
}
var output: NewsViewOutput!
@IBAction func buttonTapped() {
output.onButtonTapped()
}
var buttonTapped: Observable<Void> {
return button.rx.tap.asObservable()
}
view.buttonTapped
.subscribe(onNext: {
interactor.loadNews()
state = .loading
})
9
Реактивный ViewInput
View
ViewInput
Presenter
InteractorOutput ViewOutput
· view
· interactor
protocol NewsViewInput {
var state: PublishSubject<State> { get }
}
ViewModel
10
Реактивный вью
View
ViewInput
ViewOutput
Presenter
InteractorOutput
· view
· interactor
ViewProtocolprotocol NewsViewProtocol {
var state: PublishSubject<State> { get }
var buttonTapped: Observable<Void> { get }
}
1. Меньше протоколов.
2. Вью не привязан к презентеру.
11
Реактивный интерактор
Interactor Presenter View
InteractorInput ViewProtocolInteractorOutput
· output · view
· interactor
InteractorProtocol
1. Ещё меньше протоколов.
2. Вью и интерактор ничего не знают про презентер.
12
Установление связей
Presenter View
ViewProtocol
PresenterProtocol
Interactor
InteractorProtocol
Assembly
view.buttonTapped
.map { [unowned self] in self.date.value }
.bind(to: interactor.loadNews)
.disposed(by: disposeBag)
interactor.newsLoaded
.map { [unowned self] in self.parseLoadingResult($0) }
.bind(to: newsState)
.disposed(by: disposeBag)
viewModel.asObservable()
.bind(to: view!.state)
· view
· interactor
1. Абстрактный презентер с входами и выходами.
2. Одинаковое устройство компонентов.
13
Без протоколов
Presenter ViewInteractor
ViewProtocolPresenterProtocolInteractorProtocol
Assembly
14
Независимые слои
Assembly
ViewInteractor Presenter
Router
15
Независимые слои
View
Interactor
Presenter
Router
View
16
Module
Управление памятью
View
Interactor
Presenter
Router
Связи
class NewsModule {
var interactor: NewsInteractor!
var presenter: NewsPresenter!
var router: NewsRouter!
var moduleDisposeBag: DisposeBag!
}
class NewsViewController {
var module: NewsModule!
}
17
Итог
Interactor Presenter View
Router
Entity
Entity
Entity
RouterInput
InteractorInput
InteractorOutput
ViewInputViewOutput
· output· output · view
· interactor
Демо-приложение: https://github.com/dmitriykotenko/RxViperDemo
1. Независимые компоненты.
2. Гибкая настройка связей.
3. Меньше протоколов.
18

More Related Content

Дмитрий Котенко – Реактивный VIPER