Swift @escaping 仅适用于非空函数参数?
Posted
技术标签:
【中文标题】Swift @escaping 仅适用于非空函数参数?【英文标题】:Swift @escaping only applies to non-null function args? 【发布时间】:2019-11-16 13:18:33 【问题描述】:我从来没有真正理解 何时 在 Swift 中使用 @escaping
。我了解它的作用(即转义闭包和非转义闭包之间的区别),但是我一直依靠 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
...
这是为什么呢?谢谢!
【问题讨论】:
【参考方案1】:您可能知道,默认情况下,闭包参数无法转义。您必须添加@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
【讨论】:
2444 链接很有帮助。我认为在最后一段中,您的意思是...只是使所有闭包...默认转义。感谢您的回答! @danqing 是的,这就是我的意思。感谢您发现它!以上是关于Swift @escaping 仅适用于非空函数参数?的主要内容,如果未能解决你的问题,请参考以下文章
当 ARRAY_CONCAT 与 ARRAY_AGG 一起应用于非空数组时,为啥 BigQuery 会生成一个空数组?
弱校验之@NotNull@NotEmpty@NotBlank