Swift中的迴圈強引用 【使用無主引用以及隱式解析可選屬性解決】

小豬熊發表於2017-12-13

無主引用以及隱式解析可選屬性

兩個屬性都必須有值,並且初始化完成後永遠不會為nil。在這種場景中,需要一個類使用無主屬性,而另外一個類使用隱式解析可選屬性。

隱式解析可選型別

這種型別的可選狀態被定義為隱式解析可選型別(implicitly unwrapped optionals)。把想要用作可選的型別的後面的問號(String?)改成感嘆號(String!)來宣告一個隱式解析可選型別。

注意: 如果你在隱式解析可選型別沒有值的時候嘗試取值,會觸發執行時錯誤。和你在沒有值的普通可選型別後面加一個驚歎號一樣。

案例

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
    }
}
複製程式碼

通過在型別結尾處加上感嘆號(City!)的方式,將CountrycapitalCity屬性宣告為隱式解析可選型別的屬性。這意味著像其他可選型別一樣,capitalCity屬性的預設值為nil,但是不需要展開它的值就能訪問它。

由於capitalCity預設值為nil,一旦Country的例項在建構函式中給name屬性賦值後,整個初始化過程就完成了。這意味著一旦name屬性被賦值後,Country的建構函式就能引用並傳遞隱式的selfCountry的建構函式在賦值capitalCity時,就能將self作為引數傳遞給City的建構函式。

以上的意義在於你可以通過一條語句同時建立CountryCity的例項,而不產生迴圈強引用,並且capitalCity的屬效能被直接訪問,而不需要通過感嘆號來展開它的可選值:

var country = Country(name: "Canada", capitalName: "Ottawa")
print("\(country.name)'s capital city is called \(country.capitalCity.name)")
// 列印 “Canada's capital city is called Ottawa”
複製程式碼

在上面的例子中,使用隱式解析可選值意味著滿足了類的建構函式的兩個構造階段的要求。capitalCity屬性在初始化完成後,能像非可選值一樣使用和存取,同時還避免了迴圈強引用。

引自:http://www.piggybear.net/?p=687

相關文章