Ответ
weak ссылка автоматически становится nil, когда объект, на который она указывает, деаллоцируется системой управления памятью (ARC). Это основной механизм для разрыва сильных циклов ссылок без риска краша.
Пример с циклом и делегатом:
protocol DataLoaderDelegate: AnyObject { // Протокол должен быть class-bound
func dataLoadingDidFinish()
}
class DataLoader {
weak var delegate: DataLoaderDelegate? // 1. Слабая ссылка на делегата
func loadData() {
// Загрузка данных...
delegate?.dataLoadingDidFinish() // 2. Безопасный вызов через опционал
}
}
class ViewController: UIViewController, DataLoaderDelegate {
let loader = DataLoader()
override func viewDidLoad() {
super.viewDidLoad()
loader.delegate = self // 3. Устанавливаем себя делегатом
loader.loadData()
}
func dataLoadingDidFinish() {
print("Data loaded!")
}
}
// Сценарий:
// 1. ViewController сильно ссылается на DataLoader (свойство `loader`).
// 2. DataLoader слабо ссылается на ViewController (свойство `delegate`).
// 3. Когда пользователь закрывает экран, ViewController деаллоцируется.
// 4. Сразу после этого свойство `loader.delegate` автоматически становится `nil`.
// Цикл сильных ссылок не образовался, утечки памяти нет.
Ключевые отличия weak от unowned: |
weak |
unowned |
|---|---|---|
Всегда опциональна (var). |
Неопциональна (let или var). |
|
| Безопасно обнуляется. | При обращении к деаллоцированному объекту — краш. | |
| Используется, когда время жизни ссылаемого объекта может быть короче. | Используется, когда время жизни ссылаемого объекта точно больше или равно. |