我今天再次尝试尝试理解Swift中的保留周期和弱引用.通过阅读文档,我看到了以下代码示例,其中一个引用变量被标记为weak
阻止保留周期:
class Person { let name: String init(name: String) { self.name = name } var apartment: Apartment? deinit { print("\(name) is being deinitialized") } } class Apartment { let unit: String init(unit: String) { self.unit = unit } weak var tenant: Person? // <---- This var is marked as 'weak' deinit { print("Apartment \(unit) is being deinitialized") } } var john: Person? var unit4A: Apartment? john = Person(name: "John Appleseed") unit4A = Apartment(unit: "4A") john!.apartment = unit4A unit4A!.tenant = john john = nil // prints "John Appleseed is being deinitialized" unit4A = nil // prints "Apartment 4A is being deinitialized"
让变量变弱都有问题吗?也就是说,在Person
课堂上,我可以将apartment
变量变弱,以便我拥有
class Person { // ... weak var apartment: Apartment? // added 'weak' // ... } class Apartment { // ... weak var tenant: Person? // ... }
其中有两个相互引用的弱变量.
我在游乐场测试了它似乎工作正常,但有没有强烈的理由不这样做?在这种情况下似乎没有自然的亲子关系.
你可以做到这一点.唯一的副作用是你需要确保其他东西保留了人和公寓.在原始代码中,您只需要保留人员,公寓(与人相关)将保留给您.
严格来说,当公寓被拆除时人们没有被杀死,当人们死亡时公寓没有被拆除,因此这种情况下的弱参考是有道理的.通常最好考虑您想要的关系和所有权模型,然后决定如何实现这一目标.
为了增加接受的答案,这里是一个演示行为的具体例子.
试试这是一个游乐场:
class Person { let name: String init(name: String) { self.name = name } weak var apartment: Apartment? deinit { print("\(name) is being deinitialized") } } class Apartment { let unit: String init(unit: String) { self.unit = unit } weak var tenant: Person? // <---- This var is marked as 'weak' deinit { print("Apartment \(unit) is being deinitialized") } } class Test { var person: Person init() { person = Person(name: "Fred") let unit2B = Apartment(unit: "2B") person.apartment = unit2B unit2B.tenant = person print(person.apartment!.unit) } func test() { print(person.apartment!.unit) } } func go() { let t = Test() t.test() // crashes here! } go()
在init
课堂上Test
,已创建的公寓由本地变量保留unit2B
.当init
完成后,公寓将被释放,因为不再有任何的强引用抱着它,所以当程序崩溃test
,是因为所谓的person.apartment
现在nil
.
如果删除weak
from weak var apartment
in class Person
,则此示例不会崩溃,因为创建的公寓由class属性init
保留的person
who保留person
.
修复示例的另一种方法是使其unit2B
成为属性class Test
.然后公寓将有一个强大的参考持有它所以unit2B
不会被取消分配后init
.
如果weak
从weak var apartment
in class Person
和from weak var tenant
中删除class Apartment
,那么示例不会崩溃,但是由于两个对象彼此保持强引用而创建的保留周期Person
,Apartment
因此不会释放也不会释放.