Роутер
Определение
В контексте iOS роутер изолирует остальную часть приложения от UIKit
, т.е. создание создание всех UIViewController
, UINavigationController
, UITabBarController
и их монтаж на UIWindow
выполняется исключительно внутри роутера. Роутер отделен от всех прочих сервисов по двум причинам.
Во-первых, в UI сосредоточена большая часть различий между платформами. Инкапсуляция этих различий в отдельной сущности позволяет использовать кроссплатформенную бизнес-логику. Кроссплатформенные решения, которые игнорируют или пытаются маскировать эти UI-различия платформ, не обеспечивают «нативного look-and-feel». Побочным эффектом применения роутера также является возможность разрабатывать приложение в «headless-режиме», используя вместо настоящего роутера mock-объект. Это открывает широкие возможности для интеграционного тестирования.
Во-вторых, UI современных клиенстких приложений обладает собственным состоянием, которое надо:
- хранить;
- модифицировать согласно UI-логике;
- синхронизировать с бизнес-логикой.
Именно за эти процессы и отвечает роутер, что позволяет разрабатывать UI независимо от бизнес-логики, равно как и разрабатывать бизнес-логику, независимо от UI. Сообщения для роутера параметризуются вью-моделями, которые предоставляют роутеру полный контекст вызова. Роутер хранит свой внутренний контекст, который он самостоятельно сопоставляет с вызывающим контекстом из вью-модели, после чего принимает то или иное решение.
Графическое представление
Как и любой другой сервис, роутер описывается диаграммой состояний.
Примеры
Рассмотрим пример UI-логики. У вас приложение-магазин. В приложении есть экран с каталогом товаров, экран с карточкой товара и экран настроек. Вам поступила задача от маркетинга: обрабатывать диплинк с акцией «Носки со скидкой 90%», т.е. уметь открывать карточку акционного товара в произвольный момент времени. При этом требование UX-проектировщика — не прерывать пользовательский контекст при открытии акционной карточки. Это означает, что UI-логика открытия диплинка зависит от контекста:
- если пользователь находится на вкладке с каталогом товаров, то акционную карточку следует открыть через
push
вUINavigationController
каталога, так же, как открываются все остальные карточки товаров; - если пользователь уже находится на карточке товара, то:
- в случае совпадения текущей и акционной карточек ничего не делаем;
- в случае различия снова выполняем push карточки в навигационный стек;
- если пользователь находится на вкладке с настройками, где навигационного стека не предусмотрено, то карточку акционного товара показываем модально.
Детали реализации
Применительно к iOS инстанцирование вью-контроллеров можно перенести из роутера в фабрику вью-контроллеров. Таким образом, в роутере останется «чистая» UI-логика, которую можно покрыть тестами точно так же, как это делается с любым другим сервисом.