@escaping?Escaping closure — это замыкание, которое переживает функцию, в которую оно передано — например, completion handler, сохранённый как свойство или выполненный асинхронно после возврата из функции.
Поскольку escaping closures хранятся дольше, чем функция, они могут создать retain cycles. Это происходит когда:
self сильной ссылкойself также держит сильную ссылку на это замыканиеclass MyClass {
var completion: (() -> Void)?
func setup() {
completion = {
self.doSomething() // strong capture — retain cycle!
}
}
}
И self, и замыкание держат сильные ссылки друг на друга, что мешает ARC освободить оба объекта.
Используй capture list с [weak self] или [unowned self]:
completion = { [weak self] in
self?.doSomething() // safe — no retain cycle
}
[weak self] когда self может быть nil во время выполнения — всегда даёт optional[unowned self] только когда self гарантированно переживёт замыкание — приведёт к крашу, если self окажется nilПо умолчанию замыкания, передаваемые как параметры функции, являются non-escaping. Они выполняются внутри области видимости функции и затем отбрасываются, поэтому не создают риска retain cycles и не требуют никакой особой обработки.
Всегда используй [weak self] в escaping closures, которые обращаются к self, — особенно в async callbacks, network requests и stored completion handlers — чтобы гарантировать безопасное и предсказуемое управление памятью.
Non-escaping замыкания по умолчанию не требуют capture lists, потому что они выполняются и удаляются в пределах области видимости функции, что делает невозможным циклические ссылки.
Новый — ещё не проверен сообществом
Вы