Ответ
Coordinator и Router — это архитектурные паттерны для управления навигацией, но с разной областью ответственности.
Coordinator (Координатор):
- Управляет потоком приложения (flow). Знает, какие экраны показывать и в каком порядке.
- Содержит бизнес-логику навигации. Решает, что делать после успешного логина или покупки.
- Создает и удерживает дочерние координаторы, формируя иерархию.
- Сильно связан с логикой приложения.
Пример Coordinator:
class AppCoordinator {
private let window: UIWindow
private var childCoordinators = [Coordinator]()
func start() {
if UserDefaults.standard.isLoggedIn {
showMainFlow()
} else {
showAuthFlow()
}
}
private func showAuthFlow() {
let authCoordinator = AuthCoordinator(window: window)
authCoordinator.onSuccess = { [weak self] in
self?.childCoordinators.removeAll()
self?.showMainFlow()
}
childCoordinators.append(authCoordinator)
authCoordinator.start()
}
}
Router (Роутер):
- Отвечает только за механику перехода между конкретными ViewController'ами (push, present, dismiss).
- Не содержит бизнес-логики. Не знает, почему происходит переход, только как его выполнить.
- Обычно является слабой ссылкой (weak) от View или Presenter.
- Более простой и декларативный.
Пример Router (в VIPER):
protocol ProfileRoutingLogic {
func routeToSettings()
}
class ProfileRouter: ProfileRoutingLogic {
weak var viewController: UIViewController?
func routeToSettings() {
let settingsVC = SettingsViewController()
// Чистая механика перехода, без логики
viewController?.navigationController?.pushViewController(settingsVC, animated: true)
}
}
| Сравнение: | Аспект | Coordinator | Router |
|---|---|---|---|
| Ответственность | Поток приложения, бизнес-логика навигации | Механика переходов между VC | |
| Сложность | Высокая, управляет иерархией | Низкая, выполняет конкретные команды | |
| Использование | Часто как центральный элемент архитектуры | Компонент в паттернах типа VIPER/Clean Swift | |
| Связность | Сильная с логикой приложения | Слабая, зависит только от интерфейсов |
На практике Coordinator может использовать Router внутри себя для выполнения конкретных переходов, разделяя логику и механику.