Ответ
Да, опциональное замыкание неявно является @escaping.
Причина: Компилятор Swift не может гарантировать, что опциональное замыкание будет вызвано синхронно в пределах тела функции. Поскольку замыкание может быть nil, его вызов часто откладывается или выполняется условно, что подразумевает необходимость его сохранения (escaping).
Пример, требующий escaping:
var storedClosure: (() -> Void)? // Для хранения замыкания оно должно быть escaping
func performAsyncTask(completion: (() -> Void)?) {
// Сохранение в свойство или асинхронный вызов требуют escaping
storedClosure = completion
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
completion?() // Вызов после завершения функции — явный признак escaping
}
}
// Компилятор автоматически трактует `completion` как @escaping в этом случае.
Как сделать его non-escaping? Фактически, нет способа явно объявить опциональное замыкание как @nonescaping. Если нужно non-escaping поведение, следует:
- Избегать хранения замыкания.
- Вызывать его синхронно и гарантированно внутри функции.
- Рассмотреть возможность использования не-опционального замыкания со значением по умолчанию (например,
{}).