gpt4 book ai didi

swift - 为什么添加闭包捕获列表会阻止我的实例被释放?

转载 作者:可可西里 更新时间:2023-11-01 02:05:12 30 4
gpt4 key购买 nike

class Name {
var name: String
init(name: String) {
self.name = name
}
deinit {
print("\(name) deinit")
}
}
var x: Name? = Name(name: "abc")

var someClosure = {
print("\(x?.name)")
}

someClosure()

x = nil

然后控制台会输出:

Optional("abc")
abc deinit

可以看出调用了“deinit”函数。所以没有形成强引用循环。但是如果我在闭包中添加一个捕获列表:

var someClosure = { [x] in
print("\(x?.name)")
}

控制台会输出:

Optional("abc")

并且没有调用“deinit”函数。所以对象和引用形成了一个强引用循环。

这是什么原因?这两个条件有什么区别?

最佳答案

首先,在这两种情况下都没有强保留循环——你只是有一个全局闭包变量,它持有对你的类实例的强引用,因此防止它被释放。 p>

在您的第一个示例中,当您在闭包中捕获 x 时:

var someClosure = {
print("\(x?.name)")
}

你得到的(实际上)是对引用的引用——也就是说,闭包有一个对 x 存储的引用,然后它有一个对你的类实例的引用。当您将 x 设置为 nil 时 – 闭包仍然引用 x 的存储,但现在是 x 没有对您的类实例的引用。因此,您的类实例不再对它有任何强引用,并且可以被释放。

在您使用 capture list 的第二个示例中:

var someClosure = { [x] in
print("\(x?.name)")
}

您正在复制 x 本身——也就是说,您正在复制对您的类实例的引用。因此,只要它存在,闭包就会保留你的类。将 x 设置为 nil 不会影响闭包对您实例的引用,因为它拥有对它的强引用。

关于swift - 为什么添加闭包捕获列表会阻止我的实例被释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43421961/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com