Как устроен роутинг и какой механизм используется для навигации в iOS приложении?
Что проверяют
Понимаете ли вы, что навигация это не только pushViewController, но и место, где обычно расползается связность экранов. Спрашивают, чтобы выйти на архитектуру: кто решает, какой экран следующий, и как этот выбор тестировать.
Как отвечать
Начните с базовых механизмов UIKit:
- UINavigationController: стек экранов,
pushViewControllerиpopViewController, встроенный жест возврата; - модальные экраны:
presentповерх текущего, свой стиль показа и отдельный жизненный цикл; - UITabBarController: параллельные стеки, у каждой вкладки своя история;
- сегвеи из сториборда: наглядно на маленьком проекте, но переход зашит в разметку, и переиспользовать экран сложно.
Дальше про паттерны. Проблема простого подхода в том, что контроллер знает, какой экран открывать следующим, создаёт его и передаёт зависимости. Coordinator выносит это решение в отдельный объект: экран сообщает координатору о событии («нажали на товар»), а тот собирает и показывает следующий. Экран становится переиспользуемым, а сценарий целиком тестируется без интерфейса. В VIPER ту же роль играет Router.
В SwiftUI навигация декларативная: NavigationStack с привязкой к массиву пути и navigationDestination, состояние навигации это обычные данные. Отсюда удобство диплинков: пришла ссылка, положили в путь нужную цепочку экранов и она открылась целиком.
Хорошо закончить практикой: как передаёте данные назад (замыкание или делегат, а не прямая ссылка на предыдущий контроллер) и как обрабатываете push-уведомление, которое должно открыть конкретный экран из холодного старта.
Где спотыкаются
Держат навигацию внутри контроллера и удивляются, почему экран нельзя открыть из другого сценария.
Забывают про weak в замыканиях координатора и получают цикл ссылок вместе с утечкой экрана.
Про SwiftUI отвечают через NavigationView и NavigationLink(isActive:), не зная, что современный путь это NavigationStack с путём.