引用計(jì)數(shù)應(yīng)用于類的實(shí)例。結(jié)構(gòu)體和枚舉類型是值類型,不是引用類型,也不是通過引用的方法存儲(chǔ)和傳遞。
弱引用
聲明屬性或者變量時(shí),在前面加上weak關(guān)鍵字表明這是一個(gè)弱引用。(當(dāng)arc設(shè)置弱引用為nil時(shí),屬性觀察不會(huì)被觸發(fā))
class Person {
let name : String
init(name:String) {
self.name = name
}
var apartment : Apartment?
deinit {
print("\(name) is being delloc")
}
}
class Apartment {
let name : String
init(name:String) {
self.name = name
}
weak var person : Person?
deinit {
print("\(name) is being empty")
}
}
var building : Apartment?
var person : Person?
building = Apartment(name: "愛情公寓")
person = Person(name: "美嘉")
building!.person = person
person!.apartment = building
person = nil
無主引用
和弱引用不同的是,無主引用在其他實(shí)例有相同或者更長(zhǎng)的生命周期時(shí)使用。在關(guān)鍵字前添加 unowned表示。
重要
使用無主引用,你必須確保引用始終指向一個(gè)未銷毀的實(shí)例。
如果你試圖在實(shí)例被銷毀后訪問該實(shí)例的無主引用,會(huì)觸發(fā)運(yùn)行時(shí)錯(cuò)誤。
class Customer {
let name : String
var card : CreditCard?
init(name:String) {
self.name = name
}
deinit {
print("Custimer delloc")
}
}
class CreditCard {
let name : String
unowned var customer : Customer
init(name:String,cutomer:Customer) {
self.name = name
self.customer = cutomer
}
deinit {
print("CreditCard delloc")
}
}
var john : Customer?
john = Customer(name: "John")
john?.card = CreditCard(name: "card", cutomer: john!)
john = nil
Person和Apartment的例子展示了二個(gè)屬性的值都允許為nil,這種場(chǎng)景適合用弱引用來解決。
Customer和CreditCard的例子展示了一個(gè)屬性的值不允許為nil,這種場(chǎng)景適合用無主引用解決。
當(dāng)兩個(gè)屬性均可不為nil且互相引用時(shí),如下
class Country {
let name : String
var city : City!
init(name:String,cityName:String) {
self.name = name
self.city = City(name:cityName,country:self)
}
}
class City {
let name : String
unowned let country : Country
init(name:String,country:Country) {
self.name = name
self.country = country
}
}
解決閉包引起的循環(huán)引用
以下是造成了循環(huán)引用的代碼。
class HTMLElement {
let name : String
let text : String?
lazy var asHTML : () -> String = {
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("銷毀")
}
}
解決方法:聲明每個(gè)引用為弱引用或者無主引用。
注意
swift有以下要求:只要在閉包內(nèi)使用self成員,就要用self.name,self.someMethod(),而不是name,someMethod()。
使用無主引用:在閉包和捕獲的實(shí)例總是互相引用并且總是同時(shí)銷毀時(shí),將閉包內(nèi)的捕獲定義為無主引用。
弱引用:在被捕獲的引用可能會(huì)變?yōu)閚il時(shí),將閉包內(nèi)捕獲的定義為弱引用。
如果被捕獲的引用絕對(duì)不會(huì)變?yōu)閚il,應(yīng)該用無主引用。