← Назад к вопросам

В каком случае можем написать weak let?

2.2 Middle🔥 141 комментариев
#Управление памятью

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Когда используется weak let в Swift?

weak let — это комбинация ключевых слов, используемая для объявления слабой ссылки (weak) на константу (let) в Swift. Это возможно, потому что weak ссылки в Swift всегда являются опциональными (Optional), даже если они объявлены через let. Значение такой константы может измениться с some instance на nil автоматически, когда на объект больше нет сильных ссылок.

Основной случай использования: предотвращение циклов сильных ссылок

Главная цель — разорвать циклы сильных ссылок (retain cycles) между экземплярами классов, особенно в отношениях родитель-дочерний или при использовании замыканий. weak ссылка не увеличивает счетчик ссылок (reference count) на объект, позволяя ARC (Automatic Reference Counting) освободить память, когда сильные ссылки исчезают.

Типичные сценарии:

  1. Делегаты (Delegates) и протоколы
    Наиболее классический пример. Объект-делегат обычно объявляется как weak, чтобы избежать цикла ссылок, где объект владеет своим делегатом, а делегат в ответ держит сильную ссылку на объект.

    protocol MyDelegate: AnyObject { } // Протокол должен быть class-bound
    
    class Controller {
        weak let delegate: MyDelegate? // weak let - делегат не должен удерживать Controller
        
        init(delegate: MyDelegate) {
            self.delegate = delegate
        }
    }
    
  2. Замыкания (Closures)
    При захвате self в замыкании, если замыкание хранится как свойство класса, может возникнуть цикл ссылок. weak используется для захвата self без сильной ссылки.

    class DataManager {
        var completion: (() -> Void)?
        
        func fetchData() {
            API.request { [weak self] in // Захватываем self как слабую ссылку
                guard let self = self else { return }
                self.handleResponse() // Теперь strong reference только внутри scope
            }
        }
    }
    

    Здесь weak let не используется напрямую, но принцип схож: захваченная ссылка становится слабой и опциональной.

  3. Иерархии объектов (например, родитель-ребенок)
    Когда два объекта ссылаются друг на друга, один из ссылок должен быть weak.

    class Parent {
        let child: Child
        init() {
            child = Child(parent: self)
        }
    }
    
    class Child {
        weak let parent: Parent? // weak let предотвращает цикл
        
        init(parent: Parent) {
            self.parent = parent
        }
    }
    

Важные технические нюансы

  • weak ссылки всегда Optional: Поскольку ARC может обнулить (nil) weak ссылку в любой момент, когда объект освобождается, тип всегда является опциональным. Даже weak let — это константа, но ее значение может меняться с .some на nil системой ARC, а не кодом разработчика.

  • Отличие от unowned:

    • weak — опциональная, автоматически обнуляемая ссылка.
    • unowned — неопциональная, предполагает, что объект жив дольше, но если объект освобожден, обращение вызовет краш.
      unowned можно объявить и как let, но это рискованно.
  • Производительность: weak ссылки требуют дополнительных затрат, так как ARC обновляет их до nil при освобождении объекта. Используйте их только при необходимости.

Пример с weak let и делегатом

class NetworkService {
    weak let delegate: NetworkServiceDelegate? // weak let константа
    
    init(delegate: NetworkServiceDelegate) {
        self.delegate = delegate // Присваивается один раз
    }
    
    func process() {
        delegate?.didReceiveData() // Может стать nil, если делегат освобожден
    }
}

Здесь delegate — константа (let), но weak позволяет ARC обнулить ее, когда делегат будет освобожден. Повторное присвоение невозможно из-за let.

Заключение

weak let используется для создания неизменяемой слабой ссылки, которая помогает предотвратить циклы сильных ссылок в отношениях между объектами, где один объект не должен владеть другим. Основные сферы применения:

  • Паттерн делегирования (delegation pattern)
  • Иерархические связи (например, родитель-ребенок)
  • Захват self в замыканиях, которые хранятся долгосрочно

Помните, что weak ссылки автоматически обнуляются, поэтому всегда проверяйте их на nil перед использованием. Правильное применение weak и unowned — ключ к избежанию утечек памяти в Swift.

В каком случае можем написать weak let? | PrepBro