简短回答
- 编译器使用不同的进程来分析代码。有很多关于大学编译器如何工作的讲座。所以很难给你一个正确的答案。
- 使用你需要的东西。很难估计这要花多少钱。 @escaping 和 @no-escaping 有不同的用例。
- 我没有看到缺点。使用弱是防止零售周期和内存泄漏的好方法。
说明
1:所以我真的不知道这个编译器究竟是如何工作的。但是,如果您想了解编译器通常是如何工作的,请阅读一些轻量级文章,例如 one
在我的想法中,编译器会进行词法分析、语法分析和语义分析。所以编译器会检测你是否需要转义。
2:闭包是 swift 中的一个概念,即“在事情完成后做事”。有关更多详细信息,请查看 documentation 和 here
以下信息大量基于本文what-do-mean-escaping-and-nonescaping-closures-in-swift
在 Swift 1 和 2 中,闭包默认是 @escaping。由于 Swift 3 闭包是@no-escaping。
@no-escaping clousures
当你在函数的参数中传递一个闭包时,在函数体被执行并返回编译器之前使用它。当函数结束时,传递的闭包超出范围,在内存中不再存在。
简单地说,这对开发人员来说是一种舒适的内存处理,因为他不需要关心任何事情。
@escaiping 闭包
@escaping 闭包有两个用例:
存储:当您需要将闭包存储在全局变量中时,调用函数的内存中存在的属性或任何其他存储将被执行并返回编译器。
异步执行:当你在调度队列上异步执行闭包时,队列会为你保存在内存中的闭包,以备将来使用。在这种情况下,您不知道何时执行闭包。
来自 Apple 文档
当闭包被传递为
函数的参数,但在函数返回后调用。
[...] 你可以在参数类型之前写 @escaping
表示允许闭包逃逸。
仅供参考:闭包标志着一个操作是异步的,而不是在后台线程上强制执行。
3:我没有看到使用它的缺点。使用弱是防止零售周期和内存泄漏的好方法。当你得到一个稳定的应用程序时,你应该忽略潜在的成本。但我再说一遍:使用你需要的东西。对于内存泄漏,这是一件棘手的事情,而且通常很难找到。
请参阅https://stackoverflow.com/a/34566876/4420355 以获得有关委托和内存泄漏的非常好的答案。这篇文章中还有很多进一步的链接。如果您阅读它们,您将更好/更好地了解内存泄漏将如何发生以及如何防止它们。
也看看这个帖子,和你的有点相似https://stackoverflow.com/a/46245943/4420355
编辑为 3
提问者:
我想我没听懂……那么“捕获”是什么意思,就无主自我而言,它在幕后如何真正起作用?闭包如何在不拥有对象的情况下使用 self?也许这个问题需要与stackoverflow分开
受Can a local variable's memory be accessed outside its scope?帖子示例的启发
您租了一间酒店房间。您第二天早上退房,锁上门,但“忘记”归还您的钥匙。你偷了钥匙!没有备用钥匙。所以酒店房间是锁着的。酒店老板不能再租这个房间了。现在有很多客人偷钥匙。有时每个房间实际上都是免费的,但上锁了。
有点幻想,租户是一个关闭。他租用房间(创建对房间实例的引用)。他睡在那里(异步操作)。他应该归还他的钥匙,但他没有。
据我了解,闭包并不拥有该对象。它是闭包和实例属性之间的引用。
苹果文档:
如果将闭包分配给
类实例的属性,并且该闭包的主体捕获
实例。这种捕获可能会发生,因为闭包的主体
访问实例的属性,例如 self.someProperty,或
因为闭包调用了实例上的一个方法,比如
self.someMethod()。在任何一种情况下,这些访问都会导致关闭
“捕捉”自我,创造强大的参考循环。
您可以使用weak 或unowned 解决这个强循环。在我看来,苹果用来解释weak 和unowned 之间区别的图片非常好:参见Automatic Reference Counting