Swift: 分配一个class方法给一个handler和handling weak self

Swift: Assign a class method to a handler and handling weak self

我刚刚在我正在开发的应用程序中寻找内存泄漏,并注意到以下内容会产生内存泄漏:

class SubClass {

    var didCloseHandler: (() -> Void)?

}

class MainClass {

    var subClass = SubClass()

    func setup {
        subClass.didCloseHandler = self.didCloseSubClass
    }

    func didCloseSubClass() {
        //
    }

}

这会产生一个保留循环,并且有充分的理由 - didCloseHandler 强烈捕获 MainClass,而 MainClass 强烈捕获 SubClass。

我的问题:Swift 中有没有一种方法允许我在没有保留周期的情况下将 class 方法分配给处理程序?

是的,我知道我可以使用 subClass.didCloseHandler = { [weak self] self?.didCloseSubClass() } 来做到这一点。不过,我想知道是否可以在不引入新闭包的情况下完成。

在MainClass中弱引用子类

如果您在其他地方没有对 SubClass 实例的强引用 - 您可以尝试这样的包装器:

func WeakPointer<T: AnyObject>(_ object: T, _ method: @escaping (T) -> () -> Void) -> (() -> Void) {
    return { [weak object] in
        method(object!)()
    }
}

然后像这样使用它:

func setup() {
    subClass.didCloseHandler = WeakPointer(self, MainClass.didCloseSubClass)
}

如果您在 didCloseSubClass 实现中不需要 MainClass 实例的属性 - 您可以制作此方法 static,这也将解决您的问题。

如果您在其他地方有对 SubClass 实例的强引用并且不会立即释放它 - weak var subClass 会这样做,正如已经提到的那样。

编辑: 我想出了另一个主意。它可能看起来有点复杂,但也许会有所帮助。

import Foundation

class SubClass {

    @objc dynamic func didCloseHandler() {
        print(#function)
    }

    deinit {
        print(" \(self) deinit")
    }
}

class MainClass {

    var subClass = SubClass()

    func setup() {
        if let implementation = class_getMethodImplementation(MainClass.self, #selector(didCloseSubClass)),
            let method = class_getInstanceMethod(SubClass.self, #selector(SubClass.didCloseHandler)) {
            method_setImplementation(method, implementation)
        }
    }

    @objc func didCloseSubClass() {
        print(#function)
    }

    deinit {
        print(" \(self) deinit")
    }
}

您更改 @objc dynamic 方法的闭包并将其实现设置为 setup() 中 MainClass 的实现。