Ответ
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 внутри себя для выполнения конкретных переходов, разделяя логику и механику.
Ответ 18+ 🔞
Да ты посмотри, какие умные слова придумали! Coordinator и Router, блядь. Сидят два паттерна, оба навигацией занимаются, а один — как начальник цеха, а второй — как разнорабочий с тачкой. Сейчас разберём эту хуйню, чтобы мозг не взорвался.
Ну, 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 — это уже не начальник, а, прости господи, инструмент. Отвёртка. Его задача — тупо выполнить команду «перейти из точки А в точку Б». Пушнуть, презентнуть, диcмиснуть. Он не думает, почему это нужно сделать. Его дело — как это сделать. Обычно он прицеплен к какому-нибудь ViewController'у слабой ссылкой, чтобы не создавать циклических зависимостей, этих ёбаных retain cycle.
Вот, например, в этой вашей архитектуре 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 |
|---|---|---|
| Чем занят | Управляет всем потоком, думает головой | Тупо тыкает кнопки перехода |
| Сложность | Высокая, иерархии, логика — пиздец | Низкая, как палка-копалка |
| Где юзают | Часто как стержень всей архитектуры | Как винтик в VIPER или Clean Swift |
| Связанность | Крепко впаян в логику приложения | Почти независим, знает только интерфейсы |
А на практике, умные ребята часто комбинируют: Coordinator рулит логикой, а для грязной работы — тыканья вьюконтроллеры — использует внутри себя какого-нибудь простенького Router'а. Разделение труда, ёпта! Один думает, другой — руки моет. Красота, в рот меня чих-пых!