Swift - @escaping和捕获列表澄清

时间:2018-05-01 06:11:16

标签: swift escaping closures unowned-references capture-list

我试图尽可能多地挖掘这个问题,但我仍然有一些事情没有在我脑海中得到解决,我将很感激地澄清它们。所以我做了一些问题..

  1. 编译器如何知道我要在后台线程上添加@escaping,以及强迫我使用它?
  2. 使用@escaping需要付费吗?如果没有..为什么不总是标记?如果我用@escaping标记封闭,即使我真的不需要它,会出现什么问题?当我试图这样做时...我的代码没有问题,有或没有@escaping的结果保持不变。
  3. 使用捕获列表[弱自我] [无主自我]的成本是多少? 我知道它制作了该对象的副本,所以我想暂时它需要更多的内存,但最终使用该副本将从内存中删除..所以,使用它有更多的缺点?

1 个答案:

答案 0 :(得分:2)

简短答案

  1. 编译器使用不同的进程来分析代码。有很多关于大学如何编译器工作的讲座。所以很难给你一个正确的答案。
  2. 使用您需要的东西。很难评估这个成本是多少。 @escaping和@no-escaping有不同的用例。
  3. 我没有看到缺点。使用弱是防止零售周期和内存泄漏的好方法。
  4. 解释

    1:那么这个编译器究竟是如何工作的我真的不知道。但是,如果您想了解编译器通常如何工作,请阅读一些轻量级的文章,例如one

    在我的想法中,编译器将进行词法分析,语法分析和语义分析。因此,编译器将检测您是否需要转义。

    2:闭包是一个快速的概念,你“在事情已经完成时做事”。有关详细信息,请查看documentationhere

    以下信息基于本文what-do-mean-escaping-and-nonescaping-closures-in-swift

    在Swift 1和2中,默认情况下是@escaping。由于Swift 3关闭是@ no-escaping。

    @ no-escaping clousures

      

    当您在函数的参数中传递闭包时,在函数的主体执行之前使用它并返回编译器。当函数结束时,传递的闭包超出范围并且在内存中不再存在。

    简单地说,对于开发人员来说,这是一种舒适的内存处理方式,因为他不需要关心任何事情。

    @escaiping closures

    对于@escaping闭包,有两种用例:

    存储:当您需要将闭包存储在全局变量中时,属性或调用函数之前的内存中存在的任何其他存储都会被执行并返回编译器。

    异步执行:当您在发送队列上异步执行闭包时,队列会为您保留内存中的闭包,以后可以使用。在这种情况下,您不知道闭包何时会被执行。

    来自Apple文档

      

    当闭包被传递时,闭包被称为转义函数   函数的参数,但在函数返回后调用。   [...]你可以在参数的类型之前写@escaping   表明关闭是允许逃脱的。

    FYI:Closures标志着操作是异步的,而不是在后台线程上引人注目。

    3:我没有看到使用它的缺点。使用弱是防止零售周期和内存泄漏的好方法。获得稳定的应用程序时,您应该忽略潜在的成本。但我再说一遍:用你需要的东西。随着内存泄漏,这是一个棘手的事情,往往很难找到。

    请参阅https://stackoverflow.com/a/34566876/4420355,了解有关委托和内存泄漏的非常好的答案。这篇文章中还有很多其他链接。如果您阅读它们,您将很好/更好地了解内存泄漏将如何发生以及如何防止它们。

    并查看这篇文章,它与你的https://stackoverflow.com/a/46245943/4420355

    有点类似

    编辑为3

    提问者:

      

    我想我没有把它弄好..那么它是什么意思“捕获”,它如何真正起作用于无主的自我?封闭如何使用自己而不拥有对象?也许这个问题需要与stackoverflow分开

    受帖子Can a local variable's memory be accessed outside its scope?

    的例子的启发

    您租用酒店房间。你第二天早上退房,锁门,但“忘了”把你的钥匙还给你。你偷了钥匙!没有备用钥匙。所以酒店房间是锁定的。酒店老板不能再租用这个房间了。现在有很多客人偷了钥匙。有时每个房间都是免费的但是锁定了。

    有点幻想,房客是封闭的。他租房间(创建房间实例的引用)。他睡在那里(异步操作)。他应该还给他的钥匙,但他没有。

    在我的理解中,闭包不拥有该对象。它是闭包和实例属性之间的引用。

    Apple文档:

      

    如果为a分配闭包,也会出现强引用循环   类实例的属性,该闭包的主体捕获   实例。这种捕获可能发生,因为闭合的身体   访问实例的属性,例如self.someProperty或   因为闭包调用实例上的方法,例如   self.someMethod()。在任何一种情况下,这些访问都会导致闭包   “捕捉”自我,创造一个强大的参考周期。

    您可以使用weakunowned来解决这个强大的周期。在我的opionen中,苹果用于解释weakunowned之间差异的图片非常好:请参阅Automatic Reference Counting