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 会生成一个空数组?

swift 3中的@escaping闭包函数

弱校验之@NotNull@NotEmpty@NotBlank

csharp 此版本适用于非多行文本框

iOS Multipeer 连接是不是适用于非智能手机设备?

Visual Studio 2008 Profiler 是不是适用于非托管 C++?