【问题标题】:Avoid retain cycles for function pointers in Swift避免 Swift 中函数指针的保留循环
【发布时间】:2019-05-28 18:41:13
【问题描述】:

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

示例 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 被调用!

TestClass1 deinit 被调用!

示例 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 被调用!

func1 被调用!

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

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

【问题讨论】:

  • 这个问题——和上一个一样——与 Swift 5 没有特别的关系
  • 我编辑了标题
  • 您已经链接到stackoverflow.com/a/28138300/1187415,在您的情况下,这将类似于self.funcPointer = { [unowned self] in self.func1() }
  • 顺便说一句,不要在操场上测试这个:stackoverflow.com/questions/24363384/…
  • 这是一个完美的例子,其中“闭包是函数指针”概念(来自您之前的问题)完全崩溃了。在这种情况下,闭包是一个堆分配(和 ARCed)对象,除了指向函数实现的指针之外,它还存储对 self 的强引用(导致保持 self 活动的强保留循环)。跨度>

标签: swift function-pointers


【解决方案1】:

要修复它,你必须通过弱自身调用 func1。

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

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

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

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多