传递方法而不是关闭时会发生保留循环

时间:2016-04-21 08:36:22

标签: swift memory-management closures retain-cycle

在Swift中,我们可以在ObjC中找到很好的功能:在任何地方使用闭包都可以使用方法。但它可以导致保留周期。看看这个例子:

import Foundation

class C1 {
    let closure: Void -> Void
    init(closure: Void -> Void) {
        self.closure = closure
    }

    deinit {
        print("C1 deinit")
    }
}

class C2 {
    var c1: C1!

    func initializeC1() {
        c1 = C1(closure: f)
    }

    func f() {}

    deinit {
        print("C2 deinit")
    }
}

func main() {
    let c2 = C2()
    c2.initializeC1()
}

main()

这里我们创建了周期C2 - > C1-> f - > C2。如果您运行此程序,则deinit不会被调用。但是,如果您将f中的initializeC1替换为{},例如,它将会是。{/ p>

对于常规闭包,我们可以使用捕获列表来避免强力保留,但看起来您不能将它们用于方法。 所以,问题是:我们怎样才能在这种情况下打破保留周期,是否可能呢?

1 个答案:

答案 0 :(得分:5)

当然,我们可以通过将其包装在闭包中来“弱化”绑定方法,如下所示:

import Foundation

class C1 {
    let closure: Void -> Void
    init(closure: Void -> Void) {
        self.closure = closure
    }

    deinit {
        print("C1 deinit")
    }
}

class C2 {
    var c1: C1!

    func initializeC1() {
        // HERE we wrap a method call into a closure to break retain-cycle.
        c1 = C1(closure: { [weak self] in
            self?.f()
        })
    }

    func f() {}

    deinit {
        print("C2 deinit")
    }
}

func main() {
    let c2 = C2()
    c2.initializeC1()
}

main()
//C2 deinit
//C1 deinit