一伐坏、循環(huán)引用
1.swift提供兩種方法來解決你在使用類的屬性的時候所遇到的循環(huán)引用的問題:弱引用[weak self]
和無主引用 [unowned self]
弱引用和無主引用允許循環(huán)引用中的一個實例引用另一個實例而不保持強引用
2.弱引用
弱引用不會對其引用的實例保持強引用怔匣,因而不會阻止 ARC 銷毀被引用的實例握联。這個特性阻止了引用變?yōu)檠h(huán)強引用。聲明屬性或者變量時每瞒,在前面加上weak關(guān)鍵字表明這是一個弱引用金闽。因為弱引用不會保持所引用的實例,即使引用存在剿骨,實例也有可能被銷毀代芜。因此,ARC 會在引用的實例被銷毀后自動將其賦值為nil浓利。并且因為弱引用可以允許它們的值在運行時被賦值為nil挤庇,所以它們會被定義為可選類型變量,而不是常量贷掖。
3.無主引用
和弱引用類似嫡秕,無主引用不會牢牢保持住引用的實例。和弱引用不同的是苹威,無主引用在其他實例有相同或者更長的生命周期時使用昆咽。你可以在聲明屬性或者變量時,在前面加上關(guān)鍵unowned
表示這是一個無主引用牙甫。無主引用通常都被期望擁有值掷酗。不過 ARC 無法在實例被銷毀后將無主引用設(shè)為nil,因為非可選類型的變量不允許被賦值為nil窟哺。
重要:使用無主引用泻轰,你必須確保引用始終指向一個未銷毀的實例。如果你試圖在實例被銷毀后且轨,訪問該實例的無主引用浮声,會觸發(fā)運行時錯誤亩鬼。
4.無主引用以及隱式解析可選屬性
上面弱引用和無主引用的例子涵蓋了兩種常用的需要打破循環(huán)強引用的場景。
Person和Apartment的例子展示了兩個屬性的值都允許為nil阿蝶,并會潛在的產(chǎn)生循環(huán)強引用雳锋。這種場景最適合用弱引用來解決。
Customer和CreditCard的例子展示了一個屬性的值允許為nil羡洁,而另一個屬性的值不允許為nil玷过,這也可能會產(chǎn)生循環(huán)強引用。這種場景最適合通過無主引用來解決筑煮。
5.解決閉包的強引用
定義捕獲列表
如果閉包有參數(shù)列表和返回類型辛蚊,把捕獲列表放在他們前面
lazy var someClosure: (Int, String) -> String = {
[unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
// 這里是閉包的函數(shù)體
}
如果閉包沒有指明參數(shù)列表或者返回類型,即它們會通過上下文推斷真仲,那么可以把捕獲列表和關(guān)鍵字in放在閉包最開始的地方:
lazy var someClosure: Void -> String = { [unowned self, weak delegate = self.delegate!] in
// 這里是閉包的函數(shù)體
}
弱引用和無主引用
在閉包和捕獲的實例總是互相引用并且總是同時銷毀時袋马,將閉包內(nèi)的捕獲定義為無主引用。
相反的秸应,在被捕獲的引用可能會變?yōu)閚il時虑凛,將閉包內(nèi)的捕獲定義為弱引用。弱引用總是可選類型软啼,并且當引用的實例被銷毀后桑谍,弱引用的值會自動置為nil。這使我們可以在閉包體內(nèi)檢查它們是否存在祸挪。
注意:在被捕獲的引用絕對不會變?yōu)閚il用無主引用而不是弱引用
二锣披、可選鏈
可選鏈式調(diào)用是在當前值可能為nil的可選值上請求和調(diào)用可選值的屬性,下標和方法的方法贿条。當可選值為nil的時候雹仿,調(diào)用返回nil。多個調(diào)用可以連在一起形成調(diào)用鏈整以,當其中某一個調(diào)用返回nil胧辽,那么整個調(diào)用鏈也會返回nil。
1.使用可選鏈式調(diào)用代替強制展開
可選鏈式調(diào)用返回結(jié)果和它原本的返回結(jié)果類型相同悄蕾,但是變成了可選類型票顾。
三、類型轉(zhuǎn)換
swift中用is
和as
操作實現(xiàn)類型轉(zhuǎn)換帆调。
1.檢查類型
用類型檢查操作符 is
來檢查一個實例是否屬于特定子類型奠骄,返回true或false。
var movieCount = 0
var songCount = 0
for item in library {
if item is Movie {
movieCount += 1
} else if item is Song {
songCount += 1
}
}
print("Media library contains \(movieCount) movies and \(songCount) songs")
// 打印 “Media library contains 2 movies and 3 songs”
2.向下轉(zhuǎn)型
某類型的常量或者變量可能在幕后屬于一個子類番刊,當你確定它的類型時含鳞,你可以向下轉(zhuǎn)到它的子類型,用as!
或者` as? 轉(zhuǎn)換芹务。
類型轉(zhuǎn)化會返回一個可選類型蝉绷,當確定類型的時候才使用as!
鸭廷。
3.Any和AnyObject的類型轉(zhuǎn)換
Any可以表示任何類型,包括函數(shù)類型熔吗。
AnyObject可以表示任何類類型的實例辆床。
只有你確定他們的行為和功能的時候才使用Any和AnyObject,在代碼里使用確定的類型總是最好的桅狠。
四讼载、擴展
擴展就是為一個已有的類、結(jié)構(gòu)體中跌、枚舉類型或者協(xié)議類型添加新功能咨堤。這包括在沒有權(quán)限獲取原始源代碼的情況下擴展類型的能力(即逆向建模)。擴展和 Objective-C 中的分類類似漩符。(與 Objective-C 不同的是一喘,Swift 的擴展沒有名字。)
swift中的擴展可以:
添加計算型屬性和計算型類型屬性
定義實例方法和類方法
提供新的構(gòu)造器
定義下標
定義和使用新的嵌套類型
使一個已有類型符合某個協(xié)議
在 Swift 中嗜暴,你甚至可以對協(xié)議進行擴展凸克,提供協(xié)議要求的實現(xiàn),或者添加額外的功能灼伤,從而可以讓符合協(xié)議的類型擁有這些功能触徐。
注意:擴展可以為一個類添加新的功能咪鲜,但是不能重寫已有的功能狐赡。
注意:如果你通過擴展為一個已有類型添加新功能,那么新功能對該類型的所有已有實例都是可用的疟丙,即使它們是在這個擴展定義之前創(chuàng)建的颖侄。
注意:擴展可以添加新的計算型屬性,但是不可以添加存儲型屬性享郊,也不可以為已有屬性添加屬性觀察器览祖。