当 在 Swift 中使用 @escaping
时,我从未真正理解 。我理解它的作用(即转义和非转义闭包之间的区别),但是我一直依靠 Xcode 来告诉我何时将修饰符添加到我的论点中。
我的问题是,为什么 @escaping
只适用于非 nil 闭包?这就是我的意思:
func someFunc(someArg: Int, callback: @escaping (Error?) -> Void) {
DispatchQueue.global(qos: .background).async {
...
}
}
在上面,如果我不添加 @escaping
Xcode 会给我一个错误。但是,如果我将 callback
设为可选,如下所示,保留 @escaping
会导致 Xcode 错误:
// This is wrong (Xcode complains about @escaping)
func someFunc(someArg: Int, callback: @escaping ((Error?) -> Void)?) {
DispatchQueue.global(qos: .background).async {
...
}
}
这是为什么?谢谢!
最佳答案
您可能知道,默认情况下,闭包参数无法转义。您必须添加 @escaping
以允许它们逃脱。请参阅 here 以了解闭包逃逸的含义。
更准确的说法是函数参数位置的闭包默认是非转义的。如您所知 ((Error?) -> Void)?
是 Optional<(Error?) -> Void>
的语法糖。这里,闭包类型不在“函数参数位置”。它用作泛型类型 Optional
的泛型参数。这只是我的意见,但您不认为 @escaping Optional<(Error?) -> Void>
似乎将可选标记为“转义”吗?
对于更极端的情况,元组呢?如何仅将一对闭包中的第一项标记为转义?另外,如果我有一个 T<(Error?) -> Void>
,是否保证它肯定会存储一个闭包的实例?我的意思是,它只是一个泛型类型:
class Foo<T> {}
let a: Foo<(Int) -> Int> = Foo()
那么
@escaping
应该对这个结构做什么呢?最后,包装在
Optional
中的闭包不是已经转义到那个 Optional
了吗?也许是因为要设计、实现和测试的东西太多了,Swift 团队只是将可选和元组中的所有闭包以及其他泛型类型隐式转义。
另见:SR-2444
关于ios - Swift @escaping 仅适用于非空函数参数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58891146/