简体   繁体   English

将闭包作为参数传递给单例时的Swift内存管理

[英]Swift Memory management when pass a closure as parameter to singleton

I'm aware of the fact that closure can create retain cycles if it is assigned to a property of a class and instance properties of the class are used inside of the closure. 我知道以下事实:如果将closure分配给一个类的属性,并且该类的实例属性在闭包内部使用,则它可以创建retain cycles But

1) what about the closure is not assigned to the class property but passed as parameter to a singleton's class method ? 1) 关闭没有分配给class属性,而是作为参数传递给单例的class方法呢?

2) How the memory is managed in this case ? 2) 在这种情况下如何管理内存?

In a method of my controller (UIViewController) I have something like: 在我的控制器(UIViewController)的方法中,我有类似以下内容:

MySingleton.classMethod(parameters ..., completion: { () -> Void in
   /**
   doing stuff here
   */
})

If You are not assigning the closure to a property, but just passing it to a function You need to consider if the closure will be escaping or noescape. 如果您不是将闭包分配给属性,而只是将其传递给函数,则需要考虑闭包是转义还是转义。 In Swift 3 by default all closures passed to functions are non-escaping. 在Swift 3中,默认情况下,传递给函数的所有闭包都是非转义的。

Here is a little bit more info on the matter: 以下是有关此问题的更多信息:

"noescape" - the passed closure is invoked before the return of the function “ noescape”-在函数返回之前调用传递的闭包

"escaping" - If a closure is passed as an argument to a function and it is invoked after the function returns, the closure is escaping. “转义”-如果将闭包作为参数传递给函数,并且在函数返回后调用该闭包,则闭包正在转义。

Simple explanation : We need to mark closure as escaping when we pass it to a function and the closure will be called after this function returns. 简单说明:当我们将闭包传递给函数时,需要将闭包标记为转义,并且在此函数返回后将调用闭包。

General rule is when the closure is escaping You need to use capture list to prevent retain cycles. 一般规则是闭包转义时,您需要使用捕获列表来防止保留周期。

Example

let closure = { [weak someVariable] (name: Type) -> Void in
....
// code
}

Additional info: 附加信息:

One weird thing is that optional closures are treated as escaping. 一件奇怪的事情是,可选的闭包被视为转义。 And when we explicitly add escaping keyword, there is a compile error -escaping attribute only applies to function types. 当我们显式添加转义关键字时,会出现编译错误-转义属性仅适用于函数类型。

See the below links for more info. 有关更多信息,请参见以下链接。

https://bugs.swift.org/browse/SR-2053 https://bugs.swift.org/browse/SR-2053

https://stackoverflow.com/a/39619298/5388473 https://stackoverflow.com/a/39619298/5388473

https://stackoverflow.com/a/39846519/5388473 https://stackoverflow.com/a/39846519/5388473

Update 更新
The idea of using weak or unowned in the capture lists of escaping closures is that essentially We don't know what will happen with the passed escaping closure, it may be called sometime later from another function or it may be stored in some object, which may lead to a strong retain cycle. 在转义闭包的捕获列表中使用弱或未拥有的想法是,基本上我们不知道所传递的转义闭包会发生什么,它可能稍后会从另一个函数中调用,或者可能存储在某个对象中,可能会导致强大的保留周期。

weak vs unowned vs strong capture 弱者vs无人者vs强势捕获

For more detailed information check Apple ARC docs . 有关更多详细信息,请查看Apple ARC文档

From Apple docs: 从苹果文档:

Swift provides two ways to resolve strong reference cycles when you work with properties of class type: weak references and unowned references. 使用类类型的属性时,Swift提供了两种解决强引用周期的方法:弱引用和无主引用。

Weak and unowned references enable one instance in a reference cycle to refer to the other instance without keeping a strong hold on it. 弱引用和无主引用使引用周期中的一个实例可以引用另一个实例,而无需对其进行严格控制。 The instances can then refer to each other without creating a strong reference cycle. 然后,这些实例可以相互引用,而无需创建强大的引用周期。

Use a weak reference when the other instance has a shorter lifetime—that is, when the other instance can be deallocated first. 当另一个实例的生存期较短时(即,另一个实例可以首先被释放时),请使用弱引用。 Use an unowned reference when the other instance has the same lifetime or a longer lifetime. 当另一个实例具有相同的生存期或更长的生存期时,请使用无主引用。

Keep in mind that the weak approach will add a boiler plate to the code and will be a little bit more slow, because ARC will add code for setting the weak variables to nil on their deallocation. 请记住,弱方法将在代码中添加样板,并且速度会稍慢一些,因为ARC将添加用于将弱变量设置为零的代码。 It is a good practice to follow the rules stated above, when choosing weak or unowned. 当选择弱者或无人者时,遵循上述规则是一个好习惯。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM