Правильно ли я понимаю, что эти параметры отличаются следующем: объявленное замыкание с параметром escaping будет существовать после выхода из функции в которой оно объявлено (например при передаче замыкания в качестве параметра функции)?
1 Answers
Согласно документации, вы обязаны пометить замыкание, передаваемое в функцию в качестве параметра, ключевым словом @escaping, если оно будет вызвано после возвращения из функции.
A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns
Иными словами, если замыкание (closure) будет вызвано асинхронно внутри (callback) или за пределами (delegate) функции, то вы должны его пометить как @escaping.
По сути @escaping позволяет вам отложить выполнение передаваемого в качестве параметра замыкания до нужного вам момента (например, по срабатыванию таймера или по завершению асинхронной операции).
Если вы попробуете присвоить non-escaping замыкание в свойство класса, структуры или перечисления вы получите compile-time ошибку:
class MainDispatcher {
var work: (() -> Void)? = nil
func async(_ block: () -> Void) {
self.work = block
}
}
error: assigning non-escaping parameter 'block' to an @escaping closure self.work = block
Если вы попробуете вызвать non-escaping замыкание асинхронно (то есть там где ожидается escaping замыкание), вы также получите compile-time ошибку:
class MainDispatcher {
func async(_ block: () -> Void) {
DispatchQueue.main.async {
block()
}
}
}
Closure use of non-escaping parameter 'block' may allow it to escape
По умолчанию замыкание, передаваемое в качестве параметра, является non-escaping, поэтому там, где вам необходимо вы должны использовать ключевое слово @escaping.
class MainDispatcher {
var work: (() -> Void)? = nil
func async(_ block: @escaping () -> Void) {
self.work = block
DispatchQueue.main.async {
self.work?()
}
}
func sync(_ block: () -> Void) {
DispatchQueue.main.sync {
block()
}
}
}
- 236