如果我有一个类,它将另一个类函数存储为变量,那会导致引用循环吗?
例如
class ClassA {
var i = 0
func incrementI() {
i++
}
}
class ClassB {
private var function: () -> ()
init(function: () -> ()) {
self.function = function
}
func someFunc() {
function()
}
}
我无法在ClassB中将变量函数存储为弱或无主,因此这会导致引用循环吗?或者这只是反映了我对参考周期/功能的不了解?
答案 0 :(得分:1)
参考周期正是他们的名字所暗示的。一个对象引用另一个引用原始对象的对象。这些可以由两个或多个对象组成。
为什么使用块或闭包很容易进行引用循环是因为在闭包中捕获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]
然后我们创建b,引用x1。此引用已添加到ClassB的init中。
[b]->[x1]
然后我们创建x2并引用b。 b在x2闭包中被捕获,这意味着它将保持对b的强引用。
[x2]->[b]->[x1]
我们现在为b分配一个新函数x2。这会将参考从b破坏为x1 ......
[x2]->[b]-x->[x1]
并将其替换为对x2的引用。
[x2]->[b]-\ [x1]
/\ |
\-------/
如您所见,我们现在有一个循环(或循环)参考。现在打破该引用的唯一方法是将b的函数成员设置为引用其他内容,或者将x2捕获的b值设置为其他内容。