← Назад к вопросам

Что отвечает за роутинг в Clean Swift?

1.2 Junior🔥 192 комментариев
#Язык Swift

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Роутинг в Clean Swift (VIP-цикл)

В Clean Swift архитектуре за роутинг отвечает отдельный компонент под названием Router. Его основная задача — управление переходами между сценами (ViewController'ами) и передачей данных между ними, следуя принципу однонаправленного потока данных VIP-цикла.

Роль Router в VIP-цикле

Router является конечной точкой взаимодействия внутри сцены. Он получает управление после того, как Presenter обновит ViewController, и решает, нужно ли выполнить навигационный переход. Ключевые аспекты:

  • Инкапсуляция навигационной логики: Все переходы (push, modal, pop, unwind) выносятся в Router, что делает ViewController "тупым" и переиспользуемым.
  • Работа с Data Passing: Router отвечает за передачу данных Data Store следующей сцене через Data Passing протокол.
  • Изоляция зависимости от UIKit: Навигация, жестко завязанная на UIKit (например, UINavigationController.pushViewController), абстрагируется в Router, что упрощает тестирование.

Как работает Router: код и поток данных

Рассмотрим на примере перехода от сцены "Список статей" к "Детали статьи":

  1. Interactor обрабатывает tap по ячейке, готовит данные (например, ID статьи) и передает их во ViewController через Presenter.
  2. Presenter форматирует данные в ViewModel и триггерит событие перехода.
  3. ViewController получает ViewModel и вызывает метод Router'а для перехода.
// Протокол для передачи данных МЕЖДУ сценами
protocol ArticleDetailDataPassing {
    var dataStore: ArticleDetailDataStore? { get }
}

// Router для сцены "Список статей"
protocol ArticleListRoutingLogic {
    func routeToArticleDetail()
}

final class ArticleListRouter: ArticleListRoutingLogic, ArticleDetailDataPassing {
    weak var viewController: ArticleListViewController?
    var dataStore: ArticleDetailDataStore? // Data Store следующей сцены
    
    // MARK: - Routing
    func routeToArticleDetail() {
        // 1. Получаем DataStore текущей сцены
        guard let sourceDS = viewController?.interactor as? ArticleListDataStore,
              let detailVC = ArticleDetailViewController() as? ArticleDetailViewController else { return }
        
        // 2. Настраиваем Data Passing
        var destinationDS = detailVC.router?.dataStore
        destinationDS?.articleID = sourceDS.selectedArticleID // Передаем данные
        
        // 3. Выполняем переход (навигация)
        viewController?.navigationController?.pushViewController(detailVC, animated: true)
    }
}

Ключевые паттерны и best practices

  • Data Passing через протоколы: Каждая сцена объявляет протокол [SceneName]DataPassing, который включает dataStore следующей сцены. Это обеспечивает строгую типизацию.
  • Router не содержит бизнес-логики: Он только маршрутизирует и передает данные. Решение "куда" перейти часто принимается во ViewController на основе ViewModel от Presenter'а.
  • Использование Segue (опционально): В Clean Swift можно использовать Storyboard Segue, но тогда Router конфигурирует prepare(for:sender:), изолируя эту логику от ViewController.
  • Слабая связь: Router хранит weak ссылку на ViewController, чтобы избежать retain cycle.
  • Тестируемость: Благодаря протоколам, Router легко замокать в unit-тестах Interactor'а или Presenter'а.

Отличие от обычного MVC и других архитектур

В классическом MVC навигация часто размазана между ViewController'ами, что приводит к Massive ViewController. Clean Swift решает это через Router, делая навигацию:

  • Предсказуемой: все переходы в одном месте.
  • Модифицируемой: изменение типа перехода (например, с push на modal) затрагивает только Router.
  • Безопасной: компилятор проверяет Data Passing через протоколы.

Итог: Router в Clean Swift — это централизованный, тестируемый менеджер навигации, который строго отделяет переходы между экранами от бизнес-логики и представления, следуя принципам Clean Architecture и SOLID.