在上面的例子中,ARC 會跟蹤你所新創(chuàng)建的Person實例的引用數量,并且會在Person實例不再被需要時銷毀它。
然而,我們可能會寫出這樣的代碼,一個類永遠不會有0個強引用。這種情況發(fā)生在兩個類實例互相保持對方的強引用,并讓對方不被銷毀。這就是所謂的循環(huán)強引用。
你可以通過定義類之間的關系為弱引用或者無主引用,以此替代強引用,從而解決循環(huán)強引用的問題。具體的過程在解決類實例之間的循環(huán)強引用中有描述。不管怎樣,在你學習怎樣解決循環(huán)強引用之前,很有必要了解一下它是怎樣產生的。
下面展示了一個不經意產生循環(huán)強引用的例子。例子定義了兩個類:Person和Apartment,用來建模公寓和它其中的居民:
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { println("\(name) is being deinitialized") }
}
class Apartment {
let number: Int
init(number: Int) { self.number = number }
var tenant: Person?
deinit { println("Apartment #\(number) is being deinitialized") }
}
每一個Person實例有一個類型為String,名字為name的屬性,并有一個可選的初始化為nil的apartment屬性。apartment屬性是可選的,因為一個人并不總是擁有公寓。
類似的,每個Apartment實例有一個叫number,類型為Int的屬性,并有一個可選的初始化為nil的tenant屬性。tenant屬性是可選的,因為一棟公寓并不總是有居民。
這兩個類都定義了析構函數,用以在類實例被析構的時候輸出信息。這讓你能夠知曉Person和Apartment的實例是否像預期的那樣被銷毀。
接下來的代碼片段定義了兩個可選類型的變量john和number73,并分別被設定為下面的Apartment和Person的實例。這兩個變量都被初始化為nil,并為可選的:
var john: Person?
var number73: Apartment?
現在你可以創(chuàng)建特定的Person和Apartment實例并將類實例賦值給john和number73變量:
john = Person(name: "John Appleseed")
number73 = Apartment(number: 73)
在兩個實例被創(chuàng)建和賦值后,下圖表現了強引用的關系。變量john現在有一個指向Person實例的強引用,而變量number73有一個指向Apartment實例的強引用:

現在你能夠將這兩個實例關聯在一起,這樣人就能有公寓住了,而公寓也有了房客。注意感嘆號是用來展開和訪問可選變量john和number73中的實例,這樣實例的屬性才能被賦值:
john!.apartment = number73
number73!.tenant = john
在將兩個實例聯系在一起之后,強引用的關系如圖所示:

不幸的是,將這兩個實例關聯在一起之后,一個循環(huán)強引用被創(chuàng)建了。Person實例現在有了一個指向Apartment實例的強引用,而Apartment實例也有了一個指向Person實例的強引用。因此,當你斷開john和上一篇:Swift元組下一篇:Swift閉包