Ответ
Чтобы предотвратить retain cycle (цикл сильных ссылок) в замыкании, необходимо использовать список захвата для явного указания weak или unowned ссылок на захватываемые объекты.
1. Weak Capture ([weak self]):
Рекомендуемый и безопасный подход. Делает захваченную ссылку опциональной.
class MyViewController: UIViewController {
func setupHandler() {
someAsyncTask { [weak self] in
// self — опционален (WeakReference<Self>?)
guard let strongSelf = self else {
return // Объект был освобожден
}
strongSelf.updateUI()
// Альтернативно: self?.updateUI()
}
}
}
2. Unowned Capture ([unowned self]):
Используется, когда время жизни объекта гарантированно превышает время жизни замыкания. При обращении к освобожденному объекту вызовет краш.
class MySerializer {
func serialize(completion: () -> Void) {
// Гарантируется, что `self` существует при вызове completion
performWork { [unowned self] in
self.finalize() // Прямой доступ, не опционал
}
}
}
| Ключевые различия: | weak |
unowned |
|
|---|---|---|---|
| Тип ссылки | Опциональная (T?) |
Неопциональная (T) |
|
| Поведение при dealloc | Автоматически становится nil |
Остается висячей ссылкой (dangling) | |
| Безопасность | Безопасен, требует проверки | Небезопасен, может привести к крашу | |
| Использование | Когда объект может быть освобожден | Когда объект переживает замыкание |
Правило: В большинстве асинхронных сценариев используйте [weak self]. [unowned self] применяйте только при абсолютной уверенности в жизненном цикле.