class Name {
var name: String
init(name: String) {
self.name = name
}
deinit {
print("\(name) deinit")
}
}
var x: Name? = Name(name: "abc")
var someClosure = {
print("\(x?.name)")
}
someClosure()
x = nil
然后控制台会输出:
Optional("abc")
abc deinit
可以看出调用了“deinit”函数。所以没有形成强引用循环。 但是如果我在闭包中添加一个捕获列表:
var someClosure = { [x] in
print("\(x?.name)")
}
控制台会输出:
Optional("abc")
并且没有调用“deinit”函数。所以对象和引用形成了一个强引用循环。
这是什么原因?这两个条件有什么区别?
最佳答案
首先,在这两种情况下都没有强保留循环——你只是有一个全局闭包变量,它持有对你的类实例的强引用,因此防止它被释放。 p>
在您的第一个示例中,当您在闭包中捕获 x
时:
var someClosure = {
print("\(x?.name)")
}
你得到的(实际上)是对引用的引用——也就是说,闭包有一个对 x
存储的引用,然后它有一个对你的类实例的引用。当您将 x
设置为 nil
时 – 闭包仍然引用 x
的存储,但现在是 x
没有对您的类实例的引用。因此,您的类实例不再对它有任何强引用,并且可以被释放。
在您使用 capture list 的第二个示例中:
var someClosure = { [x] in
print("\(x?.name)")
}
您正在复制 x
本身——也就是说,您正在复制对您的类实例的引用。因此,只要它存在,闭包就会保留你的类。将 x
设置为 nil
不会影响闭包对您实例的引用,因为它拥有对它的强引用。
关于swift - 为什么添加闭包捕获列表会阻止我的实例被释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43421961/