Давайте рассмотрим шаг за шагом (строка за строкой)
// Weak 1
runClosure { [weak self] in
В первой строке создается ссылка на целевой объект, ссылка которого по совпадению (или нет) называется self
.
self?.isInner = false
В приведенной выше строке используется слабая ссылка, она не влияет на жизненный цикл целевого объекта.
guard let strongSelf = self else { return }
Теперь эта строка действительно создает сильную ссылку на целевой объект, что продлит срок службы объектов как минимум на strongSelf
. Теперь, в зависимости от агрессивности компилятора, strongSelf
может умереть после прохождения этой строки (последняя ссылка в коде) или после завершения выполнения внешнего замыкания.
// Can this [weak self] create problems?
// Weak 2
strongSelf.runClosure { [weak self] in
Теперь это имеет почти тот же эффект, что и захват с внешней крышки. Он создает ссылку на, возможно, уже освобожденный экземпляр (в зависимости от того, * strongSelf
все еще жив или нет).
self?.isInner = true
Это обычное необязательное использование, не влияющее на целевое время жизни.
Теперь, при условии, что runClosure
работает асинхронно, нет никаких проблем с целевым объектом, живущим больше, чем ожидалось (при условии, что больше нет сильных ссылок).
Подводя итог, можно сказать, что время жизни объекта определяется количеством сильных ссылок на этот объект. Как только все сильные ссылки будут уничтожены, объект будет автоматически освобожден. В вашем конкретном сценарии внутреннее замыкание слабо фиксирует и уже является слабой ссылкой, и это не влияет на жизненный цикл целевого объекта. Единственный игрок - strongSelf
, который уничтожается не позднее уничтожения внешнего закрытия.