Какие способы передачи данных между экранами существуют и каковы их недостатки
Что проверяют
Знаете ли вы способы не списком, а по направлению: вперёд на следующий экран, назад с результатом, между несвязанными экранами. И видите ли у каждого цену: связность, утечки памяти, неявность. Следом часто спрашивают, как то же самое делается в SwiftUI.
Как отвечать
Вперёд:
- инъекция через инициализатор:
DetailViewController(item:)или свойство передpush. Самый явный путь, зависимость видна в сигнатуре; - segue: данные передаются в
prepare(for:sender:). Минусы: строковые идентификаторы, приведениеsegue.destination, логика размазана между кодом и storyboard.
Назад:
- делегат: протокол плюс
weak var delegate. Связность слабая, но много шаблонного кода ради одного события; - замыкание:
onSelect: (Item) -> Void. Короче делегата, но без[weak self]легко получить цикл удержания.
Широковещательно и глобально:
NotificationCenter: один ко многим, но связь неявная, данные вuserInfoбез типов, трудно понять, кто подписан. Наблюдатель с блоком возвращает токен, который нужно хранить и снимать;- Combine или
AsyncStream: типизированный поток событий, но за подписками надо следить; - общая модель или синглтон: удобно, но это глобальное состояние, которое мешает тестам. Лучше внедрять сервис через DI.
В SwiftUI: @Binding для двусторонней связи с родителем, @Environment с моделью на @Observable, NavigationStack с navigationDestination(for:), куда передаётся значение, а не готовый экран. Для UIKit стоит упомянуть координатор: экраны не знают друг о друге, переходы и передачу данных решает он.
Где спотыкаются
Объявляют делегат сильной ссылкой. Экран держит делегата, делегат держит экран, и оба никогда не освобождаются.
Используют UserDefaults как шину между экранами. Это хранилище настроек, а не канал связи: данные переживают экран, пишутся на диск и всплывают там, где их не ждут.
Пишут segue.destination as! DetailViewController, когда целевой экран обёрнут в UINavigationController. Приведение не проходит, и приложение падает прямо на переходе.