当 在 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/

10-10 10:28