作者:手机用户2502875921 | 来源:互联网 | 2023-08-14 18:15
我从来没有真正了解何时在Swift中使用@escaping
。我了解它的作用(即转义和非转义闭包之间的区别),但是tbf我一直都依靠Xcode告诉我何时将修饰符添加到参数中。
我的问题是,为什么@escaping
仅适用于非空闭包?这就是我的意思:
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>
,是否可以保证它肯定会存储闭包的实例?我的意思是,这是 just 一个通用类型:
class Foo {}
let a: Foo<(Int) -> Int> = Foo()
那么@escaping
应该在这个结构上做什么?
最后,难道没有将封装在Optional
中的闭包转义到那个Optional
吗?
也许是因为要设计,实现和测试的东西太多,Swift团队才使所有闭包都成为了可选对象和元组以及其他隐式转义的泛型类型。
另请参阅:SR-2444