为什么Swift闭包无法捕获自我? [英] Why Swift closure not capture self?
问题描述
我正在使用Xcode游乐场测试快速关闭.
I was testing swift closure with Xcode playground.
这是我的代码:
import UIKit
class A{
var closure: ()->() = {}
var name: String = "A"
init() {
self.closure = {
self.name = self.name + " Plus"
}
}
deinit {
print(name + " is deinit")
}
}
var a: A?
a = A()
a = nil
不出所料,a是闭包自包含的,因此a不会被释放.
As what is expected, a is self contained by closure, so a is never released.
但是,当我在最后一行之前添加此行时:
But, when I add this line before the last line:
a?.closure = { a?.name = "ttt" }
然后,我在输出窗口中发现"A is deinit",这意味着a被释放. 为什么?是不可回收的参考吗?
Then, I found "A is deinit" in the output window, which means a is released. Why? is a not recycle reference?
为了测试,我使用一个函数来设置闭包,其代码为版本2:
To be test, I use a function to set the closure, which the code is version 2:
import UIKit
class A{
var closure: ()->() = {}
func funcToSetClosure(){
self.closure = { self.name = "BBB"}
}
var name: String = "A"
init() {
self.closure = {
self.name = self.name + " Plus"
}
}
deinit {
print(name + " is deinit")
}
}
var a: A?
a = A()
a?.funcToSetClosure()
a = nil
同样,a永远不会被释放.
Again, a is never released.
所以我得出结论,当闭包是由init或类中的函数设置的时,它将导致回收引用,而当它在类之外被设置时,则不会导致回收引用.我说的对吗?
So I got the conclusion, when closure is set by init or a function in the class, it will cause recycle reference, when it is set out side the class, it will not cause recycle reference. Am I right?
推荐答案
在两种情况下都有保留周期.区别在于引用的性质,而不是设置了closure
的 place .这种差异体现在中断周期所需的时间上:
There are retain cycles in both cases. The difference is the nature of the reference, not the place where closure
is set. This difference is manifested in what it takes to break the cycle:
- 在内部"情况下,闭包内部的引用为
self
.当您释放对a
的引用时,即表示不足会中断该循环,因为该循环是直接自引用的.要中断周期,您还必须先 将a.closure
设置为nil
,然后再将a
设置为nil
,但是您没有这样做.
- In the "inside" situation, the reference inside the closure is
self
. When you release your reference toa
, that is insufficient to break the cycle, because the cycle is directly self-referential. To break the cycle, you would have had also to seta.closure
tonil
before settinga
tonil
, and you didn't do that.
- 在外部"情况下,引用为
a
.只要您的a
引用未设置为nil
,就会有一个保留周期.但是您最终要做将其设置为nil
,这足以打破周期.
- In the "outside" situation, the reference is
a
. There is a retain cycle so long as youra
reference is not set tonil
. But you eventually do set it tonil
, which is sufficient to break the cycle.
(插图来自Xcode的内存图功能.太酷了.)
(Illustrations come from Xcode's memory graph feature. So cool.)
这篇关于为什么Swift闭包无法捕获自我?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!