循环引用
1.解决实例之间的循环强引用
(1)弱引用 : 声明属性或者变量时,在前面加上 weak 关键字
(2)无主引用 : 和弱引用类似 ,和弱引用不同的是,无主引用在其他实例有相同或者更长 的生命周期时使用 ,在关键字前加 unowned
注意:
使用无主引用,你必须确保引用始终指向一个未销毁的实例。 如果你试图在实例被销毁后,访问该实例的无主引用,会触发运行时错误。
class Customer { let name: String var card: CreditCard? init(name: String) { self.name = name } deinit { print("\(name) is being deinitialized") } } class CreditCard { let number: UInt64 unowned let customer: Customer init(number: UInt64, customer: Customer) { self.number = number self.customer = customer } deinit { print("Card #\(number) is being deinitialized") } }
总结:weak常用在可选类型(两个属性的值都允许为 nil ),unowned常用在非可选类型(一个属性的值允许为 nil ,而另一个属性的值不允许为 nil )
2.第三种场景 :两个属性都必须有值,并且初始化完成后永远不会为 nil 。在这种场 景中,需要一个类使用无主属性,而另外一个类使用隐式解析可选属性
class Country { let name: String var 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 } }
3.闭包引起的循环强引用
(1)注意:Swift 有如下要求:只要在闭包内使用 的成员,就要用 self.someProperty 或者 self.someMethod() (而 不只是 someProperty 或 someMethod() )。这提醒你可能会一不小心就捕获了 self
(2)在闭包和捕获的实例总是互相引用并且总是同时销毁时,将闭包内的捕获定义为 无主引用 。
(3)相反的,在被捕获的引用可能会变为 nil 时,将闭包内的捕获定义为 弱引用 。弱引用总是可选类型,并且当引用 的实例被销毁后,弱引用的值会自动置为 nil 。这使我们可以在闭包体内检查它们是否存在
(4)注意:如果被捕获的引用绝对不会变为 nil ,应该用无主引用,而不是弱引用
class HTMLElement { let name: String let text: String? lazy var asHTML: Void -> String = { [unowned self] in if let text = self.text { return "<\(self.name)>\(text)</\(self.name)>" } else { return "<\(self.name) />" } } init(name: String, text: String? = nil) { self.name = name self.text = text } deinit { print("\(name) is being deinitialized") } }