我知道这样一个事实:如果将< code>closure赋给一个类的属性,并且在闭包内部使用了该类的实例属性,那么它可以创建< code>retain cycles。但是
1)闭包没有分配给类属性,而是作为参数传递给单例的类方法,这是怎么回事?
2) 在这种情况下如何管理内存?
在我的控制器(UIViewController)的方法中,我有类似的东西:
MySingleton.classMethod(parameters ..., completion: { () -> Void in
/**
doing stuff here
*/
})
如果你没有把闭包赋给一个属性,而只是把它传递给一个函数,你需要考虑闭包是否会转义或者不转义。在Swift 3中,默认情况下传递给函数的所有闭包都是不可转义的。
以下是有关此事的更多信息:
“noescape”-在函数返回之前调用传递的闭包
“转义”-如果闭包作为参数传递给函数并在函数返回后调用,则闭包正在转义。
简单解释:当我们将闭包传递给函数时,需要将其标记为转义,并且该函数返回后将调用闭包。
一般规则是当闭包转义时,您需要使用捕获列表来防止保留周期。
实例
let closure = { [weak someVariable] (name: Type) -> Void in
....
// code
}
附加信息:
一件奇怪的事情是,可选的闭包被视为转义。当我们显式添加转义关键字时,存在编译错误 - 转义属性仅适用于函数类型。
有关更多信息,请参阅以下链接。
https://bugs.swift.org/browse/SR-2053
https://stackoverflow.com/a/39619298/5388473
https://stackoverflow.com/a/39846519/5388473
更新<br>在转义闭包的捕获列表中使用弱或无主的想法是,本质上我们不知道传递的转义闭关会发生什么,它可能稍后从另一个函数调用,或者可能存储在某个对象中,这可能导致强保留循环。
弱vs无主vs强捕获
有关更多详细信息,请查看Apple ARC文档。
来自苹果文档:
当您使用类类型的属性时,Swift提供了两种解决强引用循环的方法:弱引用和无主引用。
弱引用和无主引用使引用周期中的一个实例能够引用另一个实例,而无需对其进行强保持。然后,这些实例可以相互引用,而无需创建强引用循环。
当另一个实例的生存期较短时,即当另一个实例可以首先被释放时,使用弱引用。当另一个实例具有相同的生存期或更长的生存期时,使用无主引用。
请记住,弱变量方法会在代码中添加一个锅炉板,速度会稍微慢一点,因为ARC会添加代码,在释放弱变量时将它们设置为零。当选择弱或无主时,遵循上述规则是一个好的做法。
问题内容: 我试图了解Go在创建带有参数的匿名函数与将该函数用作闭包之间的区别。这是区别的一个例子。 带参数: 作为关闭: 我的问题是,第一种形式何时比第二种更好?您是否会为此类事情使用参数?我唯一看到第一种形式有用的是从另一个函数返回a时。 问题答案: 使用闭包与使用函数参数之间的区别在于共享同一变量与获取值的副本有关。请考虑下面的两个示例。 在 Closure中, 所有函数调用都将使用中存储的
我试图构造一个包含可选闭包的表。当我尝试实例化表的实例时,传递闭包的成员函数,我会得到一个编译错误。 从错误 msg 中可以看出,成员函数无法转换为可选的成员函数。我不明白为什么不;Int 或其他类型可以很容易地转换为可选类型。 无法转换类型为“”的值-
我有一个函数,它有两个参数,最后一个参数是回调闭包: 我想让第二个回调闭包参数可选。我试图将上面的函数重新定义为: 我收到编译器错误: nil默认参数值不能转换为类型'
问题内容: 我已经熟悉Android框架和Java,并希望创建一个通用的“ NetworkHelper”类,该类可以处理大多数联网代码,使我能够从中调用网页。 我遵循了来自developer.android.com的这篇文章来创建我的网络类:http : //developer.android.com/training/basics/network- ops/connecting.html 码:
问题内容: 我正在使用具有集成交付管道功能(https://jenkins.io/solutions/pipeline/)的Jenkins v2.1 来编排两个现有构建(构建和部署)。 在我的参数化构建中,我有3个用户参数设置,也需要在管道中选择该参数。 管道脚本如下: 除以外,此方法均正常运行。当我构建管道时,会引发以下错误: 如何解决此类型转换错误?甚至更好的是,有没有一种麻烦的方式可以将所有
问题内容: 我正在创建一个分页类,需要将两个参数传递给我的LIMIT子句的MySQL存储过程。 我将它们作为INT传递给我,并尝试这样的事情 但是,当我尝试保存该存储过程时,它给了我一个错误。有什么方法可以让我错过吗?还是我必须评估整个查询并执行它? 问题答案: 在5.5.6之前的版本中,无法在MySQL存储过程中进行参数化。您需要动态构建查询并执行它。 在5.5.6及更高版本中,只要将存储的pr