swift - 在做惰性变量、内存管理时我们需要弱引用还是无主引用

标签 swift memory-management memory-leaks lazy-evaluation

我正在通过以下方式在 Swift 中试验内存管理。

class Person {
    let name: String
    //var block: (() -> Void)?

    init(name: String) {
        self.name = name
    }

    //  Declare variable clone, using self inside.
    private lazy var clone: String  = {
        return self.name   
    }()

    deinit {
        print("Destroying \(name)")
    }
    func doSomething() {
        print("Doing something for \(name)")
    }
}

var p2: Person? = Person(name: "p2")
print(p2!.clone)
p2 = nil

如您所见,我在声明惰性变量时在内部使用了 self,我认为它仍然没问题,因为当 p2 变为 nil 时,我可以看到 deinit 方法被调用。

但是,如果我进行如下更改

    // This is a closure
    private lazy var clone: () -> String  = {
        return self.name    // leaking memory is here
    }

现在,我遇到了内存泄漏问题。

我的问题是关于使用惰性实例化的变量,为什么即使我使用 self 也没有得到内存泄漏。我想我必须使用它,否则我会得到内存泄漏.

最佳答案

这里:

 private lazy var clone: () -> String  = {
        return self.name    // leaking memory is here
    }

您将闭包本身分配给变量,而不是分配它应该返回的 String。由于您使用的是闭包保留self,因此两者永远不会被释放,这会导致内存泄漏。当闭包作为属性保留并且闭包保留自身时,将创建一个引用循环。这是 捕获列表 发挥作用的地方。您可以像这样修复泄漏:

private lazy var clone: () -> String  = { [unowned self] in

        return self.name    // leaking memory is fixed
    }

Selfcapture lists 中声明为 unowned,因为可以安全地假设它NOT在任何时候都是 nil。如果您确定变量永远不会nil,请使用unowned,但如果您认为在某些时候它可能变为 nil,使用 weak 代替。

关于swift - 在做惰性变量、内存管理时我们需要弱引用还是无主引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38725424/

相关文章:

对 C 中 free() 的用法感到困惑

C++ 函数初始化和内存泄漏

c - NtQuerySystemInformation - 内存泄漏

swift - Sprite Kit - 有时球会从屏幕上消失?

swift - 快速播放解析中的音乐

ios - Sprite 在暂停和取消暂停后移动两个位置

ios - 如何在 SWIFTUI 主体内运行函数?

c - 为字符缓冲区分配可变长度数组

dictionary - 在 Go 中,删除指针映射的条目会导致内存泄漏?

c - Valgrind 中是否需要处理仍然可达的内存?