关闭和保留周期

closure and retain cycle

我正在尝试将闭包从一个 class 传递到另一个。
但是我得到了一个保留周期。我是闭包和保留周期的新手。
我花了几个小时阅读教程,但我不明白如何去做。

我有两个 classes A 和 B。B 持有 A 的一个实例。
A 有一个 属性 类型的闭包。 B 将闭包设置为他的方法之一。
当 B“单击”B 时调用 A 中使用闭包的方法。

我知道我有一个保留周期,因为我没有得到 deinit 打印。
我的输出是:

b clicked
b_case
from b

而不是:

b clicked
b_case
from b
Deinitialization B
Deinitialization A

谢谢

class A {
    var b_code:(()->Void)?
    var b_case = false
    func DoSomeThing () {
        if b_case {
            print("b_case")
            b_code!()
        }
        else {
            print ("other case")
        }
    }
    init () {}
    deinit {
        print ("Deinitialization A")
    }
}

class B {
    let a = A()
    let b_value = "from b"
    
    
    init(){
        a.b_case = true
        a.b_code = someCode
    }
    deinit {
        print ("Deinitialization B")
    }
    
    func someCode () {
        print(b_value)
    }
    
    func click () {
        print ("b clicked")
        a.DoSomeThing()
    }
}

var b : B? = B()
b!.click()
b = nil

你是对的。 B 正在保留 A,但 A 正在保留其 b_code 属性 引用(捕获)B 的函数。这是一个保留周期。

I am trying to pass a closure from one class to another

不,你不是。在这一行

 a.b_code = someCode

术语someCode不是闭包。这是一个方法参考。就是这个问题。

改变

a.b_code = someCode

a.b_code = { [weak self] in print(self?.b_value) }

或者可能

a.b_code = { [weak self] in self?.someCode() }

关键是您必须为 b_code 分配一个匿名函数(您称之为闭包),而不是方法引用,因为这是您可以拥有一个捕获列表的唯一方式,可以让您管理捕获对 self 的引用的内存以打破保留周期。