1删咱、面向協(xié)議
從Swift基礎(chǔ)庫(kù)的角度來(lái)說(shuō),定義的協(xié)議數(shù)量遠(yuǎn)比定義的類多很多
Swift協(xié)議可擴(kuò)展,并通過(guò)擴(kuò)展提供默認(rèn)實(shí)現(xiàn)模庐,這也是Swift面向協(xié)議的核心
Swift協(xié)議支持泛型
Swift協(xié)議使用范圍更廣,并非像OC中只有類才能遵循協(xié)議油宜,Swift中結(jié)構(gòu)體(Int掂碱、String怜姿、Array等也是結(jié)構(gòu)體)、枚舉疼燥、類都能遵循協(xié)議
2沧卢、枚舉增強(qiáng)
OC中枚舉,枚舉量的值都是整型數(shù)據(jù)醉者,而Swift中但狭,枚舉量的值,除了Int撬即,可以是字符串等類型(只能是字符串立磁、整形、浮點(diǎn)型這三種)
Swift中枚舉剥槐,可以增加參數(shù)
Swift中枚舉唱歧,可以增加方法
Swift中枚舉,可以遵循協(xié)議
很多功能的設(shè)計(jì)都依賴于Swift的枚舉才沧,如可選型的定義迈喉、Alamofire中的Result等
經(jīng)常會(huì)遇到枚舉量想跟字符串綁定,OC中枚舉温圆,需要單獨(dú)去定義字典去映射挨摸,Swift則不需要,甚至可以在定義枚舉的時(shí)候就處理好這種映射
3岁歉、Swift中的類有更多特性
swift中的類就是普通的一個(gè)類得运,并沒(méi)有特定意義的基類(OC中是NSObject)
swift中的類一般不具備運(yùn)行時(shí)特性,除非是繼承自NSObject的類锅移,或者是增加@objc修飾
swift類支持內(nèi)部類
swift類泛型支持遠(yuǎn)比OC靈活和強(qiáng)大
swift類支持方法重載
4熔掺、函數(shù)更靈活
支持函數(shù)嵌套
支持多返回值(新增了元組數(shù)據(jù)類型)
支持參數(shù)默認(rèn)值
5、for\switch等語(yǔ)句更靈活
for遍歷方式更多
switch不僅僅只支持整型非剃,也支持字符串等類型
代碼示例:
1置逻、for循環(huán)
//在swift之前的版本中,聲明一個(gè)空數(shù)組變量备绽,如果不指定元素類型券坞,會(huì)默認(rèn)為元素是NSObject類型,但是現(xiàn)在不行肺素,必須指定元素類型
var arr:[Int] = [1,3,2,8,6,7]
//直接遍歷
for i in arr{
print(i)
}
//元組方式遍歷
for (indexTemp,valueTemp) in arr.enumerated(){
print("元素下標(biāo):\(indexTemp)恨锚,元素值:\(valueTemp)")
}
//常規(guī)方式遍歷,在swift3之中已經(jīng)被移除了
//for var i = 0; i<arr.count; i += 1 {
//
//}
//for in可以通過(guò)區(qū)間遍歷
for i in 3...21{
print(i)
}
2、while循環(huán)與repeat while(swift中不再叫do while倍靡,而是repeat while)
print("\n\nwhile循環(huán)")
var whileInt = 10
while whileInt>0 {
print(whileInt)
whileInt -= 1
}
print("\n\nrepeat while循環(huán)")
whileInt = 10
repeat{
print(whileInt)
whileInt -= 1
}while whileInt>0
/*
控制轉(zhuǎn)移語(yǔ)句:
break猴伶,終止本層循環(huán),如一個(gè)for循環(huán),會(huì)直接終止這個(gè)for循環(huán)
continue他挎,只終止本輪循環(huán)筝尾,不會(huì)終止整層循環(huán),不再執(zhí)行continue之后的語(yǔ)句雇盖,直接開啟下一次循環(huán)
return 函數(shù)體中調(diào)用忿等,結(jié)束整個(gè)函數(shù)
*/
6、if else
// if條件語(yǔ)句崔挖,必須是bool值贸街,并不是像其他語(yǔ)言那樣非0就默認(rèn)為true
if cConditon1 == 1{
print(cConditon1)
}
else{
}
//例外的情況是,if let解包可以用=號(hào)狸相,否則必須傳入bool值或進(jìn)行邏輯運(yùn)算</pre>
### Switch
swift中switch語(yǔ)句十分強(qiáng)大薛匪,并不限定于整型,
swift中switch的case語(yǔ)句會(huì)默認(rèn)break脓鹃,不需要顯示寫
但可以通過(guò)fallthrough逸尖,取消掉break中斷,達(dá)到OC中繼續(xù)執(zhí)行之后的case的效果
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n61" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; position: relative !important;">/*
*/
var switchInt = 4
switch switchInt {
//case 3.1..<10.2:
// print("5")
case let x where x<10:
print("case let 的形式直接取值")
case 1..<5,6...10:
print("switchInt = \(switchInt)")
case 2:
print("condition = \(2)")
default:
print("No Result")
}
var switchStr = "Abc"
switch switchStr {
case "a","AB":
print("a")
//case 5:
// print("5tt")
case "Abc":
print(switchStr)
default:
print("default")
}
var switchTuple = (5,"tuple")
switch switchTuple {
case (1..<6,_):
print("YES")
fallthrough
case (_ , _):
print(switchTuple)
fallthrough
case (4 , _):
print("fallthrough 4")
case (let x,"tuple")://可以用var修飾
print(x)
case (let x, let y):
print(x,y,"YES")
default:
print("default")
}
var switchArray = ["A","ab","AG"]
switch switchArray {
case ["A"]:
print("A")
default:
print("default")
}
var switchRange = 1..<10
switch switchRange {
case 2..<5://必須為半開區(qū)間瘸右,不能為閉區(qū)間
print(switchRange)
default:
print("default")
}
//需要注意的是
//但case變量需要和條件變量類型一致(或者case 變量所表示的區(qū)間值類型娇跟,需要和條件變量類型一致),這點(diǎn)是相同的太颤,
//并且比如switch條件為區(qū)間苞俘,那么case條件必須為區(qū)間,而switch條件為整型龄章,case條件可以為整型也可以為整型區(qū)間
//switch的case下吃谣,必須攜帶一句可執(zhí)行的語(yǔ)句,可以是空語(yǔ)句
//switch的每個(gè)case做裙,默認(rèn)包含break岗憋,不會(huì)因?yàn)槁慴reak而繼續(xù)執(zhí)行下一個(gè)case,如果想像其他語(yǔ)言一樣锚贱,達(dá)到某個(gè)case條件時(shí)繼續(xù)向下執(zhí)行case仔戈,那么可以使用fallthrough關(guān)鍵字
//switch中的的每個(gè)case語(yǔ)句,條件可以是多個(gè)拧廊,表示或杂穷,用逗號(hào)隔開,只要滿足其中一項(xiàng)卦绣,就達(dá)到這個(gè)case執(zhí)行的條件
//switch中,default語(yǔ)句可以不寫飞蚓,但是必須滿足所有列出的case已經(jīng)窮舉出switch條件所有的可能性
7滤港、類型安全
強(qiáng)類型語(yǔ)言:swift在變量聲明的時(shí)候,必須顯示的聲明類型,類型一旦確定溅漾,不可更改
可選性的定義山叮,使得開發(fā)者必須去考慮空的情況
Swift是靜態(tài)語(yǔ)言,有類型診斷添履,OC是動(dòng)態(tài)語(yǔ)言
8屁倔、注重值類型
swift與OC很大的區(qū)別之一在于,Array暮胧、Dictionary锐借、Set等,不再是引用類型往衷,而是基于結(jié)構(gòu)體的值類型
我們?cè)贠C看到的絕大多數(shù)常見(jiàn)的數(shù)據(jù)類型钞翔,在Swift中都是值類型,甚至針對(duì)UIKit席舍,還出了一套側(cè)重于值類型的SwiftUI框架
9布轿、支持運(yùn)算符重載
10、變量名稱更靈活
var 名字 = "name"
var ?? = "表情"
print(名字,??)
//變量名不局限于字母
11来颤、強(qiáng)大的泛型支持
協(xié)議支持泛型
泛型約束更靈活多樣
12汰扭、支持多種派發(fā)方式
swift支持靜態(tài)派發(fā)(效率高)、動(dòng)態(tài)派發(fā)(函數(shù)表派發(fā)福铅、消息派發(fā))方式萝毛,OC支持動(dòng)態(tài)派發(fā)(消息派發(fā))方式。
1本讥、直接派發(fā)(Direct Dispatch)
靜態(tài)派發(fā)珊泳,又叫做早期綁定,是指在編譯期將方法調(diào)用綁定到方法的實(shí)現(xiàn)上拷沸,這種派發(fā)方式非成椋快。在編譯期撞芍,編譯器可以看到調(diào)用方和被調(diào)方的所有信息秧了,直接生成跳轉(zhuǎn)代碼,這樣在運(yùn)行期就不會(huì)有其它額外的開銷序无。并且編譯器可以根據(jù)自己知道的信息進(jìn)行優(yōu)化验毡,比如內(nèi)聯(lián),可以極大提高程序運(yùn)行效率帝嗡。
在 Swift 中晶通,結(jié)構(gòu)體和枚舉的方法調(diào)用,以及被 final
標(biāo)記的類和類的方法哟玷,都會(huì)采用這種派發(fā)方式狮辽。
直接派發(fā)是最快的,不止是因?yàn)樾枰{(diào)用的指令集會(huì)更少,并且編譯器還能夠有很大的優(yōu)化空間,例如函數(shù)內(nèi)聯(lián)等,直接派發(fā)也有人稱為靜態(tài)調(diào)用。 然而,對(duì)于編程來(lái)說(shuō)直接調(diào)用也是最大的局限,而且因?yàn)槿狈?dòng)態(tài)性所以沒(méi)辦法支持繼承和多態(tài)。
- 2喉脖、函數(shù)表派發(fā)(Table Dispatch)
函數(shù)表派發(fā)是編譯型語(yǔ)言實(shí)現(xiàn)動(dòng)態(tài)行為最常見(jiàn)的實(shí)現(xiàn)方式函數(shù)表使用了一個(gè)數(shù)組來(lái)存儲(chǔ)類聲明的每一個(gè)函數(shù)的指針.大部分語(yǔ)言把這個(gè)稱為virtual table"虛函數(shù)表), Swift里稱為“witness table.每一個(gè)類都會(huì)維護(hù)一個(gè)函數(shù)表,里面記錄著類所有的函數(shù),如果父類函數(shù)被 override的話,表里面只會(huì)保存被 override之后的函數(shù).一個(gè)子類新添加的函數(shù),都會(huì)被插入到這個(gè)數(shù)組的最后運(yùn)行時(shí)會(huì)根據(jù)這一個(gè)表去決定實(shí)際要被調(diào)用的函數(shù) 查表是一種簡(jiǎn)單,易實(shí)現(xiàn),而且性能可預(yù)知的方式.然而,這種派發(fā)方式比起直接派發(fā)還是慢一點(diǎn)從字節(jié)碼角度來(lái)看,多了兩次讀和一次跳轉(zhuǎn),由此帶來(lái)了性能的損耗.另一個(gè)慢的原因在于編譯器可能會(huì)由于函數(shù)內(nèi)執(zhí)行的任務(wù)導(dǎo)致無(wú)法優(yōu)化(如果函數(shù)帶有副作用的話) 這種基于數(shù)組的實(shí)現(xiàn),缺陷在于函數(shù)表無(wú)法拓展.子類會(huì)在虛數(shù)函數(shù)表的最后插入新的函數(shù),沒(méi)有位置可以讓 extension安全地插入函數(shù).
- 3椰苟、消息機(jī)制派發(fā)(Message Dispatch)
消息機(jī)制是調(diào)用函數(shù)最動(dòng)態(tài)的方式.也是Ccoa的基石,這樣的機(jī)制催生了kvo, UIAppearence和 CoreData等功能.這種運(yùn)作方式的關(guān)鍵在于開發(fā)者可以在運(yùn)行時(shí)改變函數(shù)的行為.不止可以通過(guò) swizzling來(lái)改變,甚至可以用 isa-swizzling修改對(duì)象的繼承關(guān)系可以在面向?qū)ο蟮幕A(chǔ)上實(shí)現(xiàn)自定義派發(fā). Swift運(yùn)行時(shí) 純 Swift類的函數(shù)調(diào)用已經(jīng)不再是 Objective-c的行時(shí)發(fā)消息,而是類似C++的vtable,在編譯時(shí)就確定了調(diào)用哪個(gè)函數(shù),所以沒(méi)法通過(guò) runtime獲取方法、屬性树叽。 而Swift為了兼容 Objective-C,凡是繼承自 NSObjec的類都會(huì)保留其動(dòng)態(tài)性,所以我們能通過(guò) runtime拿到他的方法舆蝴。這里有一點(diǎn)說(shuō)明:老版本的 Swift(如2.2)是編譯期隱式的自動(dòng)幫你加上了@objc,而40以后版本的 Swift編譯期去掉了隱式特性,必須使用顯式添加。 不管是純Swift類還是繼承自 NSObject的類只要在屬性和方法前面添加@objc關(guān)鍵字就可以使用 runtime. 項(xiàng)目 原始定義 擴(kuò)展 值類型 直接派發(fā) 直接派發(fā) 協(xié)議 函數(shù)表派發(fā) 直接派發(fā) 類 函數(shù)表派發(fā) 直接派發(fā) 繼承自NSObject的類 函數(shù)表派發(fā) 消息機(jī)制派發(fā)
- 小結(jié)
值類型總是會(huì)使用直接派發(fā),簡(jiǎn)單易懂 而協(xié)議和類的 extension都會(huì)使用直接派發(fā) NSObject的 extension會(huì)使用消息機(jī)制進(jìn)行派發(fā) NSObject聲明作用域里的函數(shù)都會(huì)使用函數(shù)表進(jìn)行派發(fā). 協(xié)議里聲明的,并且?guī)в心J(rèn)實(shí)現(xiàn)的函數(shù)會(huì)使用函數(shù)表進(jìn)行派發(fā) 一些關(guān)鍵字的派發(fā)機(jī)制
關(guān)鍵字 機(jī)制 final 直接派發(fā) dynamic 消息機(jī)制派發(fā) @objc & @nonobjc 改變?cè)贠C里的可見(jiàn)性 @inline 告訴編譯器可以直接派發(fā) Swift 運(yùn)行時(shí)-final @objc
可以在標(biāo)記為 final的同時(shí),也使用@objc讓函數(shù)可以使用消息機(jī)制派發(fā).這么做的結(jié)果就是,調(diào)用函數(shù)的時(shí)候會(huì)使用直接派發(fā),但也會(huì)在 Objective-c的運(yùn)行時(shí)里注冊(cè)響應(yīng)的 selector.函數(shù)可以響應(yīng) perform(selector)以及別的 Objective-C特性但在直接調(diào)用時(shí)又可以有直接派發(fā)的性能.
13题诵、能更靈活地支持函數(shù)式編程(鏈?zhǔn)秸{(diào)用)
14洁仗、有命名空間
- 使得一個(gè)項(xiàng)目中同名文件或者同名類可以存在
15、有更嚴(yán)格的訪問(wèn)控制
open>public>internal(默認(rèn)仇轻,無(wú)需顯示聲明)>fileprivate>private
OC中京痢,我們一般很少去使用訪問(wèn)控制符,并且OC的類篷店,都是能被子類繼承的
Swift中祭椰,如果一個(gè)類不想被子類繼承,可以用final修飾
Swift中疲陕,open修飾的類方淤,才能在其他模塊中被訪問(wèn)和繼承,并且open修飾的類中蹄殃,如果方法或者屬性有open修飾携茂,也才能被重寫
Swift中,public修飾的類型诅岩,在其他模塊只能訪問(wèn)讳苦,如果是類,只能被訪問(wèn)吩谦,不能被繼承
Swift中鸳谜,internal修飾的類型(默認(rèn)修飾符,無(wú)須顯示聲明)是默認(rèn)權(quán)限. 在模塊內(nèi)的文件,其類定義和函數(shù)定義是互相可見(jiàn)的,但是模塊外是不可見(jiàn)的,所以它又可理解為:對(duì)模塊私有.
Swift中式廷,private修飾的類型咐扭,只能在當(dāng)前private修飾類型(或者變量、方法)的所在作用域內(nèi)被訪問(wèn)
Swift中滑废,fileprivate修飾的類型蝗肪,只能當(dāng)前文件內(nèi)被訪問(wèn)
15、代碼簡(jiǎn)潔
16蠕趁、寫時(shí)拷貝特性
簡(jiǎn)而言之薛闪,寫時(shí)拷貝,就是指只是單純賦值時(shí)俺陋,不進(jìn)行拷貝逛绵,而只有發(fā)生內(nèi)容修改的時(shí)候才拷貝
如a怀各、b、c三個(gè)變量术浪,指向同一個(gè)值類型,此時(shí)并不會(huì)發(fā)生內(nèi)容拷貝寿酌,三個(gè)變量都用的同一份內(nèi)存地址
但是當(dāng)修改b的時(shí)候胰苏,只有b的內(nèi)存地址發(fā)生變化,a醇疼、c保持不變
17硕并、區(qū)間符
[n,m]閉區(qū)間,用...表示
[n,m)半開區(qū)間秧荆,用..<表示</pre>
18倔毙、語(yǔ)法糖
[1, 2, 3].map{ $0 * 2 }
[1, 2, 3] 使用了, Array 實(shí)現(xiàn)的ExpressibleByArrayLiteral 協(xié)議, 用于接收數(shù)組的字面值 map{xxx} 使用了閉包作為作為最后一個(gè)參數(shù)時(shí), 可以直接寫在調(diào)用后面, 而且, 如果是唯一參數(shù)的話, 圓括號(hào)也可以省略 閉包沒(méi)有聲明函數(shù)參數(shù), 返回值類型, 數(shù)量, 依靠的是閉包類型的自動(dòng)推斷 閉包中語(yǔ)句只有一句時(shí), 自動(dòng)將這一句的結(jié)果作為返回值 [圖片上傳失敗...(image-ce962-1708916876270)] 0, 后續(xù)參數(shù)以此類推
19、print函數(shù)(打印更靈活)
比OC的NSLog函數(shù)跟靈活
(1)支持直接打印一個(gè)變量乙濒,不局限于NSLog只能格式化輸出
(2)支持,分割打印多個(gè)變量
(3)支持"(變量名)"陕赃,快速格式化打印變量
(4)支持多個(gè)變量打印時(shí)分隔控制(separator:默認(rèn)空格 terminator:默認(rèn)換行)
var a = 12
print(a)
print("BGG"+"66666")
print("fafjfk","affdf",separator:"---")
print("rrrr","hhhhh",separator:"~~",terminator:"!!!")
//separator:默認(rèn)空格 terminator:默認(rèn)換行
print("新行嗎?")
print("a=\(a)是整數(shù)")</pre>