避免 Swift 中函数指针的保留循环

Avoid retain cycles for function pointers in Swift

让我们从这个游乐场示例开始

示例 1

import UIKit

internal final class TestClass1 {
    var testVar: Int = 1

    internal init() {
        print("TestClass1 init is called!")
    }

    deinit {
        print("TestClass1 deinit is called!")
    }

    internal func func1() {
        print("func1 is called!")
    }
}

internal final class TestClass2 {
    init() {
        let testClass1: TestClass1 = TestClass1()
        testClass1.testVar = 10
    }
}

var testClass2: TestClass2 = TestClass2()

输出

TestClass1 init is called!

TestClass1 deinit is called!

示例 2

import UIKit

internal final class TestClass1 {
    internal final var funcPointer: (() -> ())!

    internal init() {
        self.funcPointer = self.func1
        print("TestClass1 init is called!")
    }

    deinit {
        print("TestClass1 deinit is called!")
    }

    internal func func1() {
        print("func1 is called!")
    }
}

internal final class TestClass2 {
    init() {
        let testClass1: TestClass1 = TestClass1()
        testClass1.funcPointer()
    }
}

var testClass2: TestClass2 = TestClass2()

输出

TestClass1 init is called!

func1 is called!

我的问题是,deinit() 方法在示例 2 中从未被调用。我认为存在一个保留周期,但我不知道如何修复它。

我找到了这个 example and this SO 但我无法在我的示例代码中实现它。

要修复它,您必须通过 weak self 调用 func1。

internal init() {
    self.funcPointer = { [weak self] in
        self?.func1()
    }
    print("TestClass1 init is called!")
}

这样您就可以防止保留循环。

目前发生的情况是,您正在将一个实例函数分配给您的实例 属性,该实例现在对您的函数具有强引用。

希望对您有所帮助。