Функция закрытия @escaping в Swift 3
Ошибка с этой функцией ниже Closure use of non-escaping parameter 'completion' may allow it to escape
func retrieveCannedRecommendedEntities() -> Future<CannedRecommendedEntities, NSError> {
return Future() { completion in
self.retrieve(.onboarding) { response in
switch response {
case .success(let val):
let payload: AnyObject = val.value.json! as AnyObject
let json = JSON(payload)
guard let suggestions = self.parseEntitiesFromJSON(json, atKey: "suggestion") else {
completion(SqorResult.error(self.parsingError))
}
let teams = suggestions.filter {
$0.entityType != .Player
}
let athletes = suggestions.filter {
$0.entityType == .Player
}
completion(SqorResult.success(Box((teams, athletes))))
case .error(let error):
completion(SqorResult.error(error))
}
}
}
}
2 ответа
Говорят, что замыкание экранирует функцию, когда замыкание передается в качестве аргумента функции, но вызывается после ее возврата.
Если вы используете асинхронность замыкания, то есть замыкание может быть вызвано после выполнения функции, вам нужно добавить @escaping
,
Даже если у вас нет ошибок компиляции, вы можете иметь ошибку времени выполнения, потому что память закрытия может быть освобождена.
@escaping
уверяю вас, чтобы предотвратить ваше закрытие.
Ошибка компилятора означает, что параметр completion
в функции Future
- который является закрытием - указывается как "не выходящий" (это по умолчанию). Это значит, что закрытие completion
должен быть выполнен перед функцией Future
возвращается.
Однако реализация указывает на то, что completion
может "избежать" функции Future
- Который означает, что completion
может быть выполнен после функции Future
возвращается.
Для того, чтобы исправить эту ошибку программиста, вы должны убедиться, что закрытие completion
будет выполнен перед функцией Future
возвращает, или вам нужно добавить модификатор @escaping
к параметру completion
,
Смотрите также Escape E-Closures
Обратите внимание, что оба решения могут иметь последствия, потому что они либо требуют изменения API функции, возможно определенной в существующей библиотеке (например, "Future"), либо это несовместимо с вашим вариантом использования, так как вы вызываете completion
в другом - возможно, экранирующем - закрытии, которое устанавливается в качестве параметра в self.retrieve
,
Тем не менее, понятие "завершение" в контексте "будущего" четко диктует, что completion
должен быть "убегающим". Итак, добавляя @escaping
к функции подписи Future
Кажется, чтобы идти.