Паттерн делегирования (delegation) — один из ключевых в экосистеме Swift, широко используемый для передачи ответственности по обработке событий между объектами. Делегирование позволяет классу делегировать свою часть поведения другому объекту (делегату), определенному, как правило, с помощью протокола.
protocol DataUpdateDelegate: AnyObject { func didUpdateData(_ data: String) } class DataProvider { weak var delegate: DataUpdateDelegate? func updateData() { // ... логика обновления данных delegate?.didUpdateData("New data") } } class ViewController: UIViewController, DataUpdateDelegate { func didUpdateData(_ data: String) { print("Данные обновились: \(data)") } }
weak (или unowned), чтобы избежать retain cycle.AnyObject, чтобы разрешить weak-ссылки.Как вы реализуете делегирование, если у вас делегат относится к value type (например, struct)?
Ответ:
В Swift делегаты должны быть ссылочными типами (class или AnyObject), поскольку для weak-ссылки допустим только ссылочный тип. Делегатом не может выступать struct или enum, иначе возникнут проблемы: компилятор не позволит использовать weak-свойство, а strong-ссылка приведёт к retain cycle.
// Ошибка! Нельзя объявить делегат как struct: компилятор не позволит сделать его weak protocol StructDelegate { ... } struct MyStructDelegate: StructDelegate { ... } weak var delegate: StructDelegate? // Ошибка
История
В одном проекте забыли пометить свойство делегата как weak. В результате между view и делегатом возник retain cycle, приложение начало постепенно «надуваться» по памяти и крашилось через полчаса работы.
История
Делегат был реализован через value type (struct), вместо класса. IBOutlet, который должен был стать делегатом, не получал уведомлений — связи не происходило вовсе. Проблему обнаружили только после анализа логов и дебага.
История
В проекте протокол делегата не наследовал AnyObject, а свойство делегата объявили как weak var. Это привело к компиляторной ошибке, которую команде потребовалось время, чтобы понять и исправить.