我正在使用 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 永远不会被释放。
但是,当我在最后一行之前添加这一行时:
a?.closure = { a?.name = "ttt" }
然后,我在输出窗口中发现“A is deinit”,这意味着a被释放了。 为什么?是不是回收引用?
为了测试,我使用一个函数来设置闭包,代码是版本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 永远不会被释放。
所以我得出的结论是,闭包在init或者类中的函数中设置时,会引起循环引用,在类外设置时,不会引起循环引用。我说得对吗?
最佳答案
两种情况下都有循环保留。不同之处在于引用 的性质,而不是设置闭包
的地方。这种差异体现在如何打破这个循环:
- 在“内部”情况下,闭包内部的引用是
self
。当您释放对a
的引用时,不足以 打破循环,因为循环是直接自引用的。要打破循环,您还可以将a.closure
设置为nil
,然后再将a
设置为nil
,而你没有这样做。
- 在“外部”情况下,引用是
a
。只要您的a
引用未设置为nil
,就会有一个保留周期。但您最终确实将其设置为nil
,这足以打破循环。
(插图来自Xcode的内存图功能。太酷了。)
关于swift - 为什么 Swift 闭包不捕获 self ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40978533/