Swift中的强参考循环
我正在看《Swift编程语言》一书中“无主引用和隐式展开的可选属性”一节中的示例 他们的示例代码是Swift中的强参考循环,swift,Swift,我正在看《Swift编程语言》一书中“无主引用和隐式展开的可选属性”一节中的示例 他们的示例代码是 class Country { let name: String let capitalCity: City! init(name: String, capitalName: String) { self.name = name self.capitalCity = City(name: capitalName, country: self)
class Country {
let name: String
let capitalCity: City!
init(name: String, capitalName: String) {
self.name = name
self.capitalCity = City(name: capitalName, country: self)
}
}
class City {
let name: String
unowned let country: Country
init(name: String, country: Country) {
self.name = name
self.country = country
}
}
如果我只想与国家打交道,并且城市
类型的唯一目的是成为国家
的首都,这一点就行了。但是如果我想创建一个城市会发生什么呢
这会创建一个运行时异常,因为没有保留对城市
的国家
的引用,因为它是一个无主变量:
var chicago = City(name:"Chicago", country: Country(name: "USA", capitalName: "Washington DC"))
chicago.country.name // Playground execution failed: error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=EXC_I386_GPFLT).
在不创建强引用循环的情况下,我如何允许这样的事情?在您的示例中,没有人拥有
国家
实例。这意味着它会立即被释放
var country = Country(name: "USA", capitalName: "Washington DC")
var chicago = City(name:"Chicago", country: country)
chicago.country.name
将修复它,因为我们的coutry
变量将阻止USA
取消分配
如果使用无主引用,则必须始终在其他地方保留强引用。在您的示例中,没有人拥有
国家
实例。这意味着它会立即被释放
var country = Country(name: "USA", capitalName: "Washington DC")
var chicago = City(name:"Chicago", country: country)
chicago.country.name
将修复它,因为我们的coutry
变量将阻止USA
取消分配
如果使用无主引用,则必须始终在其他地方保留强引用。有两种典型的解决方案:
- 如果您想主要处理城市问题,请颠倒关系,使
强烈引用城市
,并且国家
指向一个无主实例国家
- 如果要将城市和国家作为相互交叉引用的主要对象,请将所有城市和国家放入集合(或拥有它们的其他形式的商店),并使这两个引用都变弱。这样他们就不会拥有彼此,你也不会有循环
- 第三种选择是,让
国家拥有其所有城市的集合。我认为这在这个简单的例子中是最有意义的,但这意味着
需要在其初始化中创建所有城市,或者有一个添加城市的方法国家
有两种典型的解决方案:
- 如果您想主要处理城市问题,请颠倒关系,使
强烈引用城市
,并且国家
指向一个无主实例国家
- 如果要将城市和国家作为相互交叉引用的主要对象,请将所有城市和国家放入集合(或拥有它们的其他形式的商店),并使这两个引用都变弱。这样他们就不会拥有彼此,你也不会有循环
- 第三种选择是,让
国家拥有其所有城市的集合。我认为这在这个简单的例子中是最有意义的,但这意味着
需要在其初始化中创建所有城市,或者有一个添加城市的方法国家
但如果他想用乡村级的init函数创建一个国会大厦,这是行不通的。这将是一场灾难