Как реализовать передачу данных между экранами в iOS
Что проверяют
Знаете ли вы несколько способов и умеете ли выбрать под направление передачи: вперёд, назад или всем сразу. Следом почти всегда спрашивают про retain cycle в делегате и замыкании и про то, как это делается в SwiftUI.
Как отвечать
Разложите способы по направлению потока данных:
- вперёд через инициализатор:
DetailViewController(item: item). Лучший вариант в UIKit, зависимость видна в сигнатуре и не бываетnil. Со сторибордами естьinstantiateViewController(identifier:creator:)(iOS 13+) или свойство, заполняемое вprepare(for:sender:); - назад через делегат: протокол с ограничением
AnyObjectи свойствоweak var delegate. Удобно, когда событий несколько и у них понятный контракт; - назад через замыкание:
var onSelect: ((Item) -> Void)?, внутри[weak self]. Короче делегата, когда событие одно; - широковещательно через
NotificationCenter: когда получателей много и они не знают об отправителе, например смена языка или выход из аккаунта; - общее состояние: сервис или хранилище, которое внедряют в оба экрана, а не синглтон.
В SwiftUI набор другой: @State у владельца и @Binding у дочернего экрана, модель с макросом @Observable (фреймворк Observation, iOS 17) и @Environment для того, что нужно глубоко в иерархии. Навигация идёт через NavigationStack и navigationDestination(for:): в стек кладётся значение, а экран строится по нему.
Сильный ответ добавляет, кто вообще решает о переходе: в больших проектах экраны не знают друг о друге, а сборкой и передачей данных занимается координатор или роутер.
Где спотыкаются
Объявляют делегат без weak или захватывают self в замыкании сильно. Два экрана держат друг друга, и deinit не вызывается никогда.
Обращаются к @IBOutlet нового экрана внутри prepare(for:sender:). View ещё не загружена, аутлеты равны nil, и приложение падает. Передавайте данные в обычное свойство, а в интерфейс раскладывайте в viewDidLoad.
Гонят через NotificationCenter всё подряд, даже передачу выбранного элемента на соседний экран. Связь становится неявной, строковые имена уведомлений расползаются, и отладка превращается в поиск того, кто и когда это отправил.