Ответ
@escaping — атрибут параметра-замыкания, указывающий, что замыкание может быть вызвано после возврата из функции. Требуется для асинхронных операций.
Пример с сетевым запросом:
func downloadData(from url: URL,
completion: @escaping (Result<Data, Error>) -> Void) {
URLSession.shared.dataTask(with: url) { data, _, error in
// Замыкание выполняется асинхронно, после возврата из downloadData
if let error = error {
completion(.failure(error))
} else if let data = data {
completion(.success(data))
}
}.resume()
// Функция завершается здесь, но completion ещё не вызван
}
Обязательное использование weak/unowned:
class DataLoader {
var cachedData: Data?
func loadData(completion: @escaping (Data) -> Void) {
downloadData(from: someURL) { [weak self] result in
guard let self = self else { return }
switch result {
case .success(let data):
self.cachedData = data
completion(data)
case .failure(let error):
print("Ошибка: (error)")
}
}
}
}
| Ключевые отличия: | Не-escaping (по умолчанию) |
Escaping (@escaping) |
|---|---|---|
| Вызывается до возврата функции | Может быть вызвано позже | |
| Не требует захвата self | Требует [weak self] для избежания retain cycle |
|
| Может быть mutating для value types | Не может изменять value types | |
| Оптимизируется компилятором | Меньше оптимизаций |