存储为变量的函数会导致参考循环吗?

时间:2014-12-10 12:56:32

标签: ios swift retain-cycle

如果我有一个类,它将另一个类函数存储为变量,那会导致引用循环吗?

例如

class ClassA {

    var i = 0

    func incrementI() {
        i++
    }
}

class ClassB {

    private var function: () -> ()

    init(function: () -> ()) {
        self.function = function
    }

    func someFunc() {
        function()
    }
}

我无法在ClassB中将变量函数存储为弱或无主,因此这会导致引用循环吗?或者这只是反映了我对参考周期/功能的不了解?

1 个答案:

答案 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值设置为其他内容。