Ответ
[weak self] используется в списке захвата замыкания для предотвращения циклических сильных ссылок (retain cycles). Он создает слабую (weak) ссылку на self, которая автоматически становится nil, если объект, на который она указывает, уничтожается.
Пример: асинхронная загрузка данных в UIViewController.
class MyViewController: UIViewController {
let networkService = NetworkService()
func fetchUserData() {
// Захватываем weak-ссылку на self, чтобы избежать retain cycle:
// ViewController -> networkService -> closure -> (strong) ViewController
networkService.fetchData { [weak self] result in
// 1. Проверяем, что self еще существует (не был освобожден)
guard let self = self else {
print("ViewController deallocated, ignoring callback.")
return
}
// 2. Используем self для обновления UI
self.updateUI(with: result)
self.saveToCache(result)
}
}
private func updateUI(with result: DataResult) { /* ... */ }
private func saveToCache(_ result: DataResult) { /* ... */ }
}
Когда использовать [weak self]:
- Асинхронные операции: При работе с
DispatchQueue,URLSession,Operation, коллбэками, гдеselfможет быть освобожден до выполнения замыкания. - Замыкания, хранимые в свойствах: Когда замыкание, захватывающее
self, сохраняется в свойстве того же самого объекта (например, обработчик вUIButton).
Альтернатива [unowned self]: Используется, когда вы уверены, что объект (self) точно переживет замыкание. При нарушении этого условия приведет к крашу (EXC_BAD_ACCESS). Пример: анимация, которая точно завершится до деаллокации контроллера.
UIView.animate(withDuration: 0.3) { [unowned self] in
self.view.alpha = 0.0 // Рискованно, если контроллер может быть освобожден во время анимации.
}
Best practice: В большинстве асинхронных сценариев безопаснее использовать [weak self] с последующей проверкой через guard let или optional chaining (self?.updateUI()).