微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Swift:为什么需要`@escaping`?

如何解决Swift:为什么需要`@escaping`?

我的意思是,如果编译器强制一个添加符号,那么在我看来它已经理解它是一个转义块。

为什么要强迫程序员添加它?

潮湿

解决方法

它是您函数的公共 API 的一部分。从非转义闭包更改为转义闭包是一个突破性的变化。

注解的存在是为了明确这一点。

这是一个重大更改的示例:

func f(_ closure: /* @escaping */ () -> Void) {
    closure()
}

struct AStruct {
    var i = 0
    
    mutating func mutate() {
        f { i += 1 }
    }
}

如果 f 采用非转义闭包,则一切正常。但是如果你让它@escaping,你会得到error: escaping closure captures mutating 'self' parameter

还有一些其他可能的错误与闭包捕获能够有效地将结构转换为引用类型(从而破坏任何来自值类型的保证)

,

您需要 @escaping 来区分闭包的类型,因为:

  1. 并不是所有的闭包都是“escaping”(当然,我们对异步方法使用这种转义模式,但对于函数式编程模式,闭包通常是非转义的);和

  2. 编译器可以对非转义闭包进行某些优化(例如,它如何在幕后处理内存调用),而转义闭包无法实现这些优化。

最重要的是,@escaping 限定符是让编译器知道它可以执行哪些优化所必需的。

此外,我们应该始终能够查看接口并轻松推断闭包是否正在转义。如果没有一些限定词,就很难推理一个人的代码。


FWIW,因为非转义闭包不会引入与转义闭包相同的强引用循环风险,与转义闭包相比,编译器允许对非转义闭包中的属性进行更自然的引用。通过包含/排除 @escaping 限定符,编译器还知道如何处理闭包内的 self 引用。


在遥远的过去,闭包默认为转义,我们不得不用 @noescape 注释非转义的。然后,由于 SE-0103,闭包的默认值更改为非转义,从而弃用旧的 @noescape 注释,但要求我们使用 @escaping 注释转义闭包。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。