gpt4 book ai didi

swift - 当两个属性都不能为 nil 时,unowned 在分配的内存方面有什么区别?

转载 作者:搜寻专家 更新时间:2023-11-01 06:14:16 27 4
gpt4 key购买 nike

对于我添加了 deinitializers 的 swift 编程指南中的以下代码,无论是否使用 unowned 关键字,生成的调试打印输出都是相同的。 swift 编程指南说,当引用彼此类实例的两个属性永远不会为 nil 时,使用无主和隐式展开的可选值是打破强引用循环的一种方法。如果两个属性都永远不会为零,那么这与强引用循环有何不同?例如,为什么我们在这种特殊情况下费心使用 unowned 关键字,尤其是当调试读数显示内存分配与是否使用 unowned 没有区别时?

class Country {
let name: String
var capitalCity: City!
init(name: String, capitalName: String) {
self.name = name
self.capitalCity = City(name: capitalName, country: self)
}
deinit {print("\(name) is being deinitialized")}
}

class City {
let name: String
unowned let country: Country
init(name: String, country: Country) {
self.name = name
self.country = country
}
deinit {print("\(name) is being deinitialized")}
}

var canada = Country(name: "Canada", capitalName: "Ottawa")
print("\(canada.name)'s capital city is called \(canada.capitalCity.name)")
canada.capitalCity = City(name: "Vancouver", country: canada)

调试读数:

Canada's capital city is called Ottawa
Ottawa is being deinitialized

注意:这是在 Playground 上。

最佳答案

您显然是在 Playground 或某些您不允许它们超出范围的环境中查看它(例如,如果它们是某个对象的属性,请查看当该对象本身被释放时会发生什么).但是,为了便于说明,请考虑您的代码的这种排列:

func foo() {
let canada = Country(name: "Canada", capitalName: "Ottawa")
print("\(canada.name)'s capital city is called \(canada.capitalCity.name)")
canada.capitalCity = City(name: "Vancouver", country: canada)
}

foo()

这就像你的例子,但我将这些变量的范围限制在 foo 函数内,所以我应该能够看到在其中创建和销毁的对象的完整生命周期那个范围。

使用 unowned 引用 City 中的 Country 它将报告:

Canada's capital city is called OttawaOttawa is being deinitializedCanada is being deinitializedVancouver is being deinitialized

如果没有unowned(也不是weak),它将报告:

Canada's capital city is called OttawaOttawa is being deinitialized

请注意,没有任何与“加拿大”或“温哥华”的取消初始化相关的打印语句。这是因为在没有 unowned 引用的情况下,您最终会在“Canada”和“Vancouver”之间形成一个强引用循环,并且它们不会被取消初始化。

因此,您看到“Ottawa”被取消初始化这一事实与强引用循环无关。这只是被取消初始化,因为“渥太华”被“温哥华”取代,“渥太华”没有更多的强引用,它被取消初始化。

并且您不应该就原始示例中的 deinit 中没有您的 print 语句的任何证据得出任何结论。您可以在 Playground 上完成此操作,或者它们可以是某个本身尚未被释放的对象的属性。将这些变量放在一个受限范围内,就像我在上面对 foo 函数所做的那样,可以更好地说明这些对象超出范围时的真实生命周期。它向我们展示了不解决强引用循环的结果。

最重要的是,您确实需要 City 中的 unowned(或 weak)引用来打破它强引用循环。这不仅是关于这些变量是否可以设置为 nil 的问题,而且也是它们是否有可能超出范围并被取消初始化的问题。

关于swift - 当两个属性都不能为 nil 时,unowned 在分配的内存方面有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48433325/

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