1

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

例如

class ClassA {

    var i = 0

    func incrementI() {
        i++
    }
}

class ClassB {

    private var function: () -> ()

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

    func someFunc() {
        function()
    }
}

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

4

1 回答 1

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]

然后我们使用对 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 值设置为其他内容。

于 2014-12-10T13:28:17.743 回答