【问题标题】:Swift @escaping only applies to non-null function args?Swift @escaping 仅适用于非空函数参数?
【发布时间】: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 {
    ...
    }
}

这是为什么呢?谢谢!

【问题讨论】:

    标签: ios swift


    【解决方案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 是的,这就是我的意思。感谢您发现它!
    猜你喜欢
    • 2022-10-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 2016-12-26
    • 2013-11-29
    • 2017-01-20
    相关资源
    最近更新 更多