前言
Swift,蘋果于2014年WWDC(蘋果開發(fā)者大會)發(fā)布的新開發(fā)語言,可與Objective-C?共同運(yùn)行于Mac OS和iOS平臺,用于搭建基于蘋果平臺的應(yīng)用程序。
在2016年的WWDC上,Swift 3.0是隨著iOS 10和Xcode 8一起發(fā)布的。使用Xcode 8適配Swift 3.0的過程中,你會意識到Swift 3.0有很大的改動,也許你認(rèn)為從Swift 1.2到2.0已經(jīng)是很大的改動,我覺得這真的不算什么,因為你還沒有見到swift 3.0的全貌,它的改動更多更大。本文是基于Swift 3.0帶你初步認(rèn)識Swift的基礎(chǔ)的,僅學(xué)習(xí)和參考使用。
進(jìn)入主題
1. 常量和變量
Swift中定義常量和變量分別使用 let / var? ? let:用來定義一個常量? var:用來定義一個變量。常量名和變量名是可以用中文的。
常量是不能修改的,修改是會報錯的, 變量卻是相反,是可以修改的。在Swift中定義一個常量和變量不需要寫明數(shù)據(jù)類型,因為編譯器會根據(jù)后面的數(shù)據(jù)自動推算出對應(yīng)的類型,如下圖我定義分別一個常量和一個變量。通過 option+左鍵 ?可以查看對應(yīng)的類型。 ?下面的代碼截圖中,只需要將第二行代碼刪除即可消除錯誤。

常量名和變量名使用中文如下截圖:

注意點(diǎn): ?Swift開發(fā)中每一條語句后面不需要寫分號,但是寫上去也不會報錯的,如果同一行有多條語句,那么每一條語句后面必須加上分號,不然編譯器不能區(qū)分從而報錯!
2. 數(shù)據(jù)類型轉(zhuǎn)換
Swift中不存在隱式類型轉(zhuǎn)換,所有的類型轉(zhuǎn)換必須是顯示的,因為Swift是強(qiáng)語言,OC是弱語言,寫法如下截圖。

3. Bool和Switch
Swift中的 if 使用方式基本和OC一致,但是在Swift中的 if 可以省略 () ,然而在Swift中哪怕 if 后面只有一條語句,也是不能省略 {} 的,但是在OC中是可以的。還有在OC和C或者Java中,一直有個真理:非零即真,但是在Swift中,條件只能放bool類型,所以只能是 true 或者 false。

?Swift中的Switch 后面的()可以省略掉
在OC中的Switch如果沒有break會穿透,但是在Swift中是不會的
OC中如果要在case中間定義變量,必須加上 {} 確定作用域,而在Swift中是不用的
在OC中default的位置是可以隨便寫的,只有所有的條件不滿足才會執(zhí)行default,但是在Swift中的default只能放在最后面
?OC中的default可以省略,但是在Swift中大部分是不能省略的

4. 三目運(yùn)算符(三元運(yùn)算符)和Optional(可選)
三目運(yùn)算符中的?前后一定要用空格空開,不然會報錯

Optional 是一種可選類型,代表的是可有可無,就像OC中的代理方法可以設(shè)置為Optional一樣
以后凡是看到一個方法和數(shù)據(jù)類型后面有?的,就是代表的是一個可選類型(Optional),創(chuàng)建出來的對象就有可能為nil

使用可選類型需要注意,如果直接打印可選類型,那么打印出來的值是會被Optional包裹
如果我們使用過程中遇到可選類型,可以通過使用!強(qiáng)制解析,告訴編譯器可選類型一定有值(直接在對象后面加!),如果解析后的對象不為空,那么打印出來的就不會包含Optional
但是如果我們強(qiáng)制解析,而可選類型沒有值的話,那么程序就會奔潰

5. for循環(huán)和While循環(huán)
直接上截圖 for循環(huán)

直接上截圖while循環(huán),注意點(diǎn): do while中的do沒有了,因為do被用作捕獲異常了,用 repeat 代替

6. 元組
元組(tuples)把多個值組合成一個復(fù)合值。元組內(nèi)的值可以是任意類型,并不要求是相同類型。元組很像C語言中的結(jié)構(gòu)體,但是元組其實就是值傳遞,而不是引用。元組使用的最佳場景就是當(dāng)一個函數(shù)返回多個不同的類型時,可以返回元組實現(xiàn)。

7. 數(shù)組和字典
Swift中的數(shù)組和OC中的區(qū)別就是:去掉前面的@符號 ,遍歷數(shù)組就通過元組去遍歷

Swift中的字典創(chuàng)建和創(chuàng)建數(shù)組一樣,都是用[],不過字典是通過 : 來區(qū)分一個key對應(yīng)一個值的,和數(shù)組一樣,也是通過分號(,)區(qū)分下一個元素
[String:NSObject] 類型是IOS開發(fā)中最常見的一種格式

8. 字符串
在Swift中使用 "" 定義字符串,在OC中字符串的類型是NSString,而在Swift中卻是String
在OC中字符串是一個對象,繼承于NSObject,而在Swift中字符串是一個結(jié)構(gòu)體,所以其性能要比OC中的強(qiáng)

9. 函數(shù)(方法)
Swift中函數(shù)的定義為: func +函數(shù)名字(參數(shù)名:參數(shù)類型,參數(shù)名:參數(shù)類型) -> 返回類型{}
下面截圖分別定義四種不同的函數(shù)

定義完對應(yīng)的函數(shù)后,我們要調(diào)用,調(diào)用方式為:? self.函數(shù)名 或者 直接函數(shù)名
我們可以通過函數(shù)名以及對應(yīng)類型的參數(shù)值來調(diào)用函數(shù),函數(shù)的參數(shù)傳遞的順序必須與參數(shù)列表相同。

上面的都是對應(yīng)的實例方法,下面就說一下最后的類方法(通過類名去調(diào)用)。類方法就是在實例方法的前面加關(guān)鍵字class(在func前面加class),類型方法和實例方法一樣用點(diǎn)號(.)語法調(diào)用。

10. 閉包(相當(dāng)于OC中的Block)
閉包和OC中的Block是很相似的,OC中的Block是匿名的函數(shù)
在Swift中的閉包也是用來定義一個函數(shù)回調(diào)用的,所以也是一個函數(shù)哈
閉包的基本格式: 閉包名字:(形參列表)->返回類型, (就是函數(shù)的寫法)
func easyName(finish:(_ intValue:Int)->String,_ string:String){}? // 這句代碼的意思是定義了一個名字為easyName的函數(shù),函數(shù)里面有兩個參數(shù),其中一個是閉包類型的finish , 其中一個就是String類型的string,這里面的 (_ intValue:Int)->String 就是一個閉包,閉包傳入一個Int類型和返回一個String類型
閉包的展開基本格式: { (形參列表) -> 返回值 in 需要執(zhí)行的代碼 }? // in 的含義是用于區(qū)分形參返回值和執(zhí)行代碼
// 例子 { (a:Int,b:Int)->Int in return a+b? }??? // 這句代碼的意思是: 閉包分別傳過來了兩個Int類型的a 和 b 并且要返回一個Int類型, in 后面執(zhí)行的代碼就是閉包的返回值(a+b)
1.? 函數(shù)只有一個參數(shù),并且這個參數(shù)是閉包,寫法如下:

2. 函數(shù)中的多個參數(shù)和一個閉包,寫法如下:

3. 函數(shù)中的多個參數(shù)和多個閉包,寫法如下:

4. 給閉包定義一個別名
typealias 是Swift中用來為已經(jīng)存在的類型重新定義名字的關(guān)鍵字(類似于OC語法中的 typedef),重新命名的新名字用來替代之前的類型,并且能夠使代碼變得更加清晰簡單容易理解。typealias 的用法很簡單,直接用 = 賦值就可以了
typealias <type name>= <type expression>

下面我這邊直接使用閉包別名? AllActionName2 作為函數(shù)的參數(shù)使用,如下截圖

調(diào)用函數(shù) easyUseClosure () 如下截圖結(jié)果

5. 閉包的循環(huán)引用問題
我這里先定義一個閉包的屬性,通過函數(shù)去強(qiáng)引用,然后在回調(diào)里面去調(diào)用本控制器中的view中的背景顏色,具體操作和解決方法如下:


上面函數(shù)前面的private(私有) 關(guān)鍵字? 是用來說明這個函數(shù)只能在本類中使用,是私有的函數(shù),不能被外部使用。
@escaping 關(guān)鍵字是 所有的閉包都默認(rèn)為非逃逸閉包,不再需要@noescape;如果是逃逸閉包,就用@escaping表示。? (如果這個閉包是在這個函數(shù)結(jié)束前內(nèi)被調(diào)用,就是非逃逸的即noescape。如果這個閉包是在函數(shù)執(zhí)行完后才被調(diào)用,調(diào)用的地方超過了這函數(shù)的范圍,所以叫逃逸閉包)。
?

11. 枚舉
枚舉簡單的說也是一種數(shù)據(jù)類型,只不過是這種數(shù)據(jù)類型只包含自定義的特定數(shù)據(jù),它是一組有共同特性的數(shù)據(jù)的集合
Swift 中使用 enum 關(guān)鍵詞來創(chuàng)建枚舉并且把它們的整個定義放在一對大括號內(nèi):
enum? enumname{
// 枚舉定義放在這里
}
定義如下:

使用如下截圖:

12. 結(jié)構(gòu)體
Swift 結(jié)構(gòu)體是構(gòu)建代碼所用的一種通用且靈活的構(gòu)造體,我們可以為結(jié)構(gòu)體定義屬性(常量、變量)和添加方法,從而擴(kuò)展結(jié)構(gòu)體的功能。
與 C 和 Objective C 不同的是:1. 結(jié)構(gòu)體不需要包含實現(xiàn)文件和接口。 2. 結(jié)構(gòu)體允許我們創(chuàng)建一個單一文件,且系統(tǒng)會自動生成面向其它代碼的外部接口。
結(jié)構(gòu)體總是通過被復(fù)制的方式在代碼中傳遞,因此它的值是不可修改的。
我們通過關(guān)鍵字 struct 來定義結(jié)構(gòu)體, 定義如下:

使用和調(diào)用如下:

從實例中我們可以很好的理解到: 結(jié)構(gòu)體實例是通過值傳遞的而不是通過引用傳遞。
按照通用的準(zhǔn)則,當(dāng)符合一條或多條以下條件時,請考慮構(gòu)建結(jié)構(gòu)體:
1. 結(jié)構(gòu)體的主要目的是用來封裝少量相關(guān)簡單數(shù)據(jù)值
2. 有理由預(yù)計一個結(jié)構(gòu)體實例在賦值或傳遞時,封裝的數(shù)據(jù)將會被拷貝而不是被引用
3. 任何在結(jié)構(gòu)體中儲存的值類型屬性,也將會被拷貝,而不是被引用
4. 結(jié)構(gòu)體不需要去繼承另一個已存在類型的屬性或者行為
舉例來說,以下情境中適合使用結(jié)構(gòu)體:
1. 幾何形狀的大小,封裝一個width屬性和height屬性,兩者均為Double類型
2. 一定范圍內(nèi)的路徑,封裝一個start屬性和length屬性,兩者均為Int類型
3. 三維坐標(biāo)系內(nèi)一點(diǎn),封裝x,y和z屬性,三者均為Double類型
13. 類
類是構(gòu)建代碼所用的一種通用且靈活的構(gòu)造體,我們可以為類定義屬性(常量、變量)和函數(shù)(方法)。
通過關(guān)鍵字 class + 類名 +繼承的類(可以不用繼承)+{}
與其他編程語言所不同的是,Swift 并不要求你為自定義類去創(chuàng)建獨(dú)立的接口和實現(xiàn)文件。你所要做的是在一個單一文件中定義一個類,系統(tǒng)會自動生成面向其它代碼的外部接口。
我這里新建一個TestClass的類


使用類:
類名.init()? 然后調(diào)用其里面的屬性 方法

14. 屬性和Setting以及Getting方法
在Swift中,如果在某個類中定義一個屬性,那么這個屬性是要初始化的,否則就是報錯
如果占用時不想初始化,那么可以在后面添加一個?號,可選類型

下面直接通過調(diào)用函數(shù),在函數(shù)里面賦值和打印查看效果,截圖如下:


Swift中的 set 和 get 方法直接在屬性的后面添加{ get{} set{} } 具體如下:

調(diào)用和打印如下:

在OC中通過關(guān)鍵字 readOnly 修飾 重寫 getting方法就是只讀屬性, 在Swift中 只重寫 getting方法,不重寫 setting方法就是 只讀屬性,而且這個屬性稱之為計算型屬性,這個計算型屬性是不占內(nèi)存空間的


屬性中還有一個方法可以重寫, didSet{}?? 這個當(dāng)我設(shè)置完屬性的值之后會被調(diào)用的,具體如下


15. 下標(biāo)腳本
下標(biāo)腳本可以定義在類(Class)、結(jié)構(gòu)體(structure)和枚舉(enumeration)這些目標(biāo)中,可以認(rèn)為是訪問對象、集合或序列的快捷方式,不需要再調(diào)用實例的特定的賦值和訪問方法。
舉例來說,用下標(biāo)腳本訪問一個數(shù)組(Array)實例中的元素可以這樣寫 someArray[index] ,訪問字典(Dictionary)實例中的元素可以這樣寫 someDictionary[key]。
對于同一個目標(biāo)可以定義多個下標(biāo)腳本,通過索引值類型的不同來進(jìn)行重載,而且索引值的個數(shù)可以是多個。
與定義實例方法類似,定義下標(biāo)腳本使用subscript關(guān)鍵字,顯式聲明入?yún)ⅲㄒ粋€或多個)和返回類型。
與實例方法不同的是下標(biāo)腳本可以設(shè)定為讀寫或只讀。這種方式又有點(diǎn)像計算型屬性的getter和setter
這邊我在結(jié)構(gòu)體體重定義一個下標(biāo)腳本:

調(diào)用和返回的值是:

在類中使用一個下標(biāo)腳本:

調(diào)用結(jié)果如下:

16. 繼承
一個類獲取了另外一個類的方法和屬性,這就是繼承。
當(dāng)一個類繼承其它類時,繼承類叫子類,被繼承類叫超類(或父類)。
在 Swift 中,類可以調(diào)用和訪問超類的方法,屬性和下標(biāo)腳本,并且可以重寫它們。
沒有繼承其它類的類,稱之為基類(Base Class)。
子類可以通過繼承來的實例方法,類方法,實例屬性,或下標(biāo)腳本來實現(xiàn)自己的定制功能,我們把這種行為叫重寫(overriding),我們可以使用 override 關(guān)鍵字來實現(xiàn)重寫。

調(diào)用和對應(yīng)的結(jié)果如下:

17. 類型轉(zhuǎn)換
Swift 語言類型轉(zhuǎn)換可以判斷實例的類型。也可以用于檢測實例類型是否屬于其父類或者子類的實例
Swift 中類型轉(zhuǎn)換使用 is 和 as 操作符實現(xiàn)。
is 來檢查一個實例是否屬于特定子類型。若實例屬于那個子類型,類型檢查操作符返回 true,否則返回 false。
向下轉(zhuǎn)型,用類型轉(zhuǎn)換操作符(as? 或 as!)。當(dāng)你不確定向下轉(zhuǎn)型可以成功時,用類型轉(zhuǎn)換的條件形式(as?)。條件形式的類型轉(zhuǎn)換總是返回一個可選值(optional value),并且若下轉(zhuǎn)是不可能的,可選值將是 nil。只有你可以確定向下轉(zhuǎn)型一定會成功時,才使用強(qiáng)制形式(as!)。當(dāng)你試圖向下轉(zhuǎn)型為一個不正確的類型時,強(qiáng)制形式的類型轉(zhuǎn)換會觸發(fā)一個運(yùn)行時錯誤。
類型轉(zhuǎn)換也可以用來檢查一個類是否實現(xiàn)了某個協(xié)議
Swift為不確定類型提供了兩種特殊類型別名: AnyObject可以代表任何class類型的實例。Any可以表示任何類型,包括方法類型(function types)。
我這里新建一個繼承于的SonClass的孫子類,SonClass是繼承于 baseClass的

調(diào)用和使用如下截圖:

18. 懶加載
懶加載的格式:定義變量前使用 lazy 關(guān)鍵字來修飾,后面通過賦值一個閉包
注意點(diǎn) 1.必須使用 var 2.閉包后面必須跟上()
如果閉包用于懶加載,那么in之前的代碼都可以刪掉,包括in在內(nèi)


19. 構(gòu)造方法
我這邊測試新建一個繼承NSObject的類,名字為: TestClass? 在類中添加 name hobby和age三個屬性,通過重寫構(gòu)造方法和自定義構(gòu)造方法給三個屬性分別賦值,具體操作如下:

類的函數(shù)調(diào)用和打印如下:

20. 命名空間
在Swift中,如果想使用一個類,是不需要導(dǎo)入(import)對應(yīng)的頭文件的,因為Swift中新增了一個叫做"命名空間"的概念,只要是在同一個命名的空間中,那么資源都是共享的,默認(rèn)的情況下,項目名稱就是命名空間,如下截圖,我這邊的命名空間就是:Test_Swift? ??梢詮慕貓D中看出 ViewController是在其命名空間之中的。

. 將字符串轉(zhuǎn)為類(動態(tài)獲取命名空間)
具體代碼如下:

方法的調(diào)用如下

21. 擴(kuò)展(extension),相當(dāng)于OC中的類別
給對應(yīng)的類或者系統(tǒng)的類添加方法或者屬性。
寫法: 寫在類的外面,用關(guān)鍵字 extension 修飾,后面跟隨著要擴(kuò)展的對應(yīng)的類,然后在{}里面寫要擴(kuò)展的方法或者屬性
以上面的獲取動態(tài)空間為例,我給Bundle 擴(kuò)充一個方法和一個屬性,方法就是用來獲取命名空間的,屬性的話就簡單的一個打印操作吧。具體實現(xiàn)如下截圖:

代碼的調(diào)用和打印如下:

22. 協(xié)議
協(xié)議規(guī)定了用來實現(xiàn)某一特定功能所必需的方法和屬性。
任意能夠滿足協(xié)議要求的類型被稱為遵循(conform)這個協(xié)議。
類,結(jié)構(gòu)體或枚舉類型都可以遵循協(xié)議,并提供具體實現(xiàn)來完成協(xié)議定義的方法和功能。
協(xié)議的語法格式如下:
protocol? 協(xié)議名字 { // 協(xié)議內(nèi)容 }
要使類遵循某個協(xié)議,需要在類型名稱后加上協(xié)議名稱,中間以冒號:分隔,作為類型定義的一部分。遵循多個協(xié)議時,各協(xié)議之間用逗號,分隔。
struct 結(jié)構(gòu)體名字:FirstProtocol,AnotherProtocol{ // 結(jié)構(gòu)體內(nèi)容 }
如果類在遵循協(xié)議的同時擁有父類,應(yīng)該將父類名放在協(xié)議名之前,以逗號分隔。
class 類名:父類名,FirstProtocol,AnotherProtocol{ // 類的內(nèi)容 }
具體定義一個協(xié)議和遵守如下截圖:

調(diào)用如下:

23. 泛型
Swift 的數(shù)組和字典類型都是泛型集
你可以創(chuàng)建一個Int數(shù)組,也可創(chuàng)建一個String數(shù)組,或者甚至于可以是任何其他 Swift 的類型數(shù)據(jù)數(shù)組

最后,原文Demo地址
可以通過下面的截圖快速查看和學(xué)習(xí)

