参考周期正是它们的名字所暗示的。一个对象引用另一个引用原始对象的对象。这些可以由两个或多个对象组成。
为什么使用块或闭包很容易创建引用循环是因为在闭包中捕获 self 意味着闭包对象具有对 self 的引用。如果 self 也有一个对闭包的引用,那么你就有一个引用循环。我认为您的示例是安全的,因为您在 ClassB 的 init 中传递了闭包,这意味着该闭包不应该能够引用不存在的对象。
如果您的示例将函数作为方法,那么您会遇到问题,因为您可以这样做:
class ClassB {
...
func setSomeFunc(function : ()->()) {
self.function = function
}
func printSomething() {
print("Something")
}
}
...
func test() {
var x1 = {
print("Do Nothing")
}
var b : ClassB = ClassB(x1)
var x2 = {
b.printSomething()
}
b.setSomeFunc(x2)
}
在此示例中,我们创建没有外部引用的 x1。
[x1]
然后我们使用对 x1 的引用创建 b。这个引用是在 ClassB 的 init 中添加的。
[b]->[x1]
然后我们使用对 b 的引用创建 x2。b 在 x2 闭包中被捕获,这意味着它将持有对 b 的强引用。
[x2]->[b]->[x1]
我们现在为 b 分配一个新函数 x2。这将打破从 b 到 x1 的引用...
[x2]->[b]-x->[x1]
并将其替换为对 x2 的引用。
[x2]->[b]-\ [x1]
/\ |
\-------/
如您所见,我们现在有一个循环(或循环)引用。现在打破该引用的唯一方法是将 b 的函数成员设置为引用其他内容,或者将 x2 捕获的 b 值设置为其他内容。