Swift 中的 ARC 在将 属性 分配为函数时如何解决强引用循环

ARC in Swift how to resolve strong reference cycle when assign property as function

流畅的代码,我确实尝试创建一个对象,将对象 属性 分配给一个函数。在初始化对象之后,我确实尝试将它分配给 nil。但是对象没有释放(因为 deinit 从未调用过)。

我认为问题是 属性 和所有者对象之间的强引用循环。如果这里真的有强引用循环,直接用函数赋值属性如何解决这个问题?

class MyClass {
    var aProperty: (() -> ())?

    init() {
        // problem when assign property as a method
        self.aProperty = aMethod
    }

    func aMethod() {
        print("method!!!")
    }

    deinit {
        print("MyClass is being deinitialized")
    }
}


var instance: MyClass? = MyClass()
instance?.aProperty?()
instance = nil

您通过将捕获列表定义为闭包定义的一部分来解决闭包和 class 实例之间的强引用循环。捕获列表定义了在闭包体内捕获一个或多个引用类型时使用的规则。与两个 class 实例之间的强引用循环一样,您将每个捕获的引用声明为弱引用或无主引用,而不是强引用。适当的弱或无人选择取决于代码不同部分之间的关​​系。

lazy var someClosure: Void -> String = {
[unowned self, weak delegate = self.delegate!] in
// closure body goes here

}

来自 Strong Reference Cycles for Closures

在您的情况下,您应该在将方法分配给 属性 时应用捕获列表,就像这样

init() {
    self.aProperty = { [unowned self] in self.aMethod() }
}

您仍然可以使用捕获列表来防止循环。只需将方法调用包装在闭包中,如下面的代码所示。

class MyClass {
    var aProperty: (() -> ())?

    init() {
        // use a capture list to prevent a reference cycle
        self.aProperty = { [unowned self] in self.aMethod() }
    }

    func aMethod() {
        print("method!!!")
    }

    deinit {
        print("MyClass is being deinitialized")
    }
}


var instance: MyClass? = MyClass()
instance?.aProperty?()
instance = nil

这消除了我测试中的强引用循环。