Ответ
Основная проблема — Retain Cycle (циклическая ссылка), ведущая к утечке памяти.
Как возникает:
Класс (self) имеет сильную ссылку на замыкание (например, через свойство). Замыкание, захватывая self по умолчанию (strong), создает сильную ссылку обратно на класс. Они удерживают друг друга, и счетчик ссылок никогда не станет нулевым.
Пример утечки:
class DataManager {
var onDataUpdated: (() -> Void)? // 1. Класс сильно владеет замыканием
var data = ""
func setupHandler() {
onDataUpdated = {
// 2. Замыкание по умолчанию сильно захватывает `self`
self.processData() // Strong reference back to DataManager!
}
}
func processData() { print(data) }
deinit { print("DataManager deallocated") } // Не вызовется
}
Решение: Используйте weak или unowned capture lists.
// Решение 1: [weak self] (рекомендуется, если self может стать nil)
onDataUpdated = { [weak self] in
guard let self = self else { return }
self.processData()
}
// Решение 2: [unowned self] (только если self гарантированно существует на время выполнения замыкания)
onDataUpdated = { [unowned self] in
self.processData() // Кратко, но вызовет краш, если self уже освобожден
}
Правило: Всегда анализируйте жизненный цикл. [weak self] — более безопасный выбор по умолчанию.