Ответ
Для связи между компонентами в iOS применяют несколько ключевых абстракций:
-
Протоколы (Protocols)
- Для чего: Определение четкого контракта (интерфейса) между компонентами.
- Плюсы: Строгая типизация, легкое тестирование с моками, поддержка принципа инверсии зависимостей.
protocol DataProvider { func loadItems() -> [Item] } class ViewModel { let provider: DataProvider // Зависим от абстракции }
-
Замыкания (Closures) / Колбэки
- Для чего: Передача единичных действий или результатов асинхронных операций.
- Плюсы: Простота, лаконичность для простых сценариев.
func fetchData(completion: @escaping (Result<[String], Error>) -> Void)
-
Декларативные фреймворки (Combine, SwiftUI)
- Для чего: Реактивная связь на основе данных и событий.
- Плюсы: Односторонний поток данных, автоматическое обновление UI.
class ViewModel { @Published var items: [String] = [] // Изменение автоматически уведомляет подписчиков }
-
Шина событий (NotificationCenter)
- Для чего: Широковещательная связь "многие ко многим" для слабосвязанных событий.
- Плюсы: Простота, встроена в SDK. Минусы: Отсутствие типизации, сложнее отладки.
// Отправка NotificationCenter.default.post(name: .dataDidUpdate, object: nil) // Подписка NotificationCenter.default.addObserver(...)
Выбор зависит от задачи:
- Протоколы — для строгой, тестируемой связи между слоями.
- Combine/SwiftUI — для современного реактивного UI.
- Замыкания — для простых асинхронных колбэков.
- NotificationCenter — для системных или глобальных событий.