Ответ
Non-escaping замыкание — это замыкание, которое гарантированно выполняется до завершения работы функции, в которую оно передано. Оно не сохраняется для использования после возврата из функции.
Ключевые характеристики:
- Выполняется синхронно в пределах тела функции.
- Не требует захвата
selfявно — компилятор знает, что замыкание не переживёт функцию. - Оптимизировано для производительности — не требует дополнительного выделения памяти.
Пример non-escaping замыкания:
func processItems(_ items: [Int], using processor: (Int) -> Void) {
for item in items {
processor(item) // Выполняется немедленно
}
// Замыкание больше не существует
}
// Использование
processItems([1, 2, 3]) { number in
print(number * 2) // Не нужно [weak self] или [unowned self]
}
Сравнение с escaping замыканием:
// NON-ESCAPING (по умолчанию)
func syncOperation(completion: () -> Void) {
completion() // Всегда вызывается здесь
}
// ESCAPING (требует явного указания)
func asyncOperation(completion: @escaping () -> Void) {
DispatchQueue.main.async {
completion() // Вызывается ПОСЛЕ возврата из функции
}
}
Правила использования:
- По умолчанию все замыкания в параметрах функций являются non-escaping.
- Добавляйте
@escapingтолько если замыкание будет вызвано после возврата из функции. - В non-escaping замыканиях можно изменять захваченные переменные без
inout.
Почему важно: Non-escaping замыкания безопаснее (нет риска retain cycles) и эффективнее, поэтому используются по умолчанию.