初次接觸 Swift,建議先看下 A Swift Tour
,否則思維轉(zhuǎn)換會(huì)很費(fèi)力坦胶,容易卡死或鉆牛角尖叔扼。
同樣是每一章只總結(jié)3個(gè)自己認(rèn)為最重要的點(diǎn)憋槐。這樣挺好!強(qiáng)迫你去思考去取舍和蚪。以后再看止状,也方便快速重建記憶烹棉。
注意: 個(gè)人筆記攒霹,僅供參考,不保證嚴(yán)格意義上的正確性浆洗。
The Basics
* 整數(shù),優(yōu)先使用 Int,浮點(diǎn)數(shù),優(yōu)先使用 Double
* 可以使用 0b 表示二進(jìn)制,可以在數(shù)字中間插入可讀字符 _,如 182_3880_25
* as 僅用于兼容類(lèi)型間的相互轉(zhuǎn)換.非兼容類(lèi)型的轉(zhuǎn)換,由各個(gè)類(lèi)自己的初始化方法實(shí)現(xiàn).
Basic Operators
* 空格對(duì)操作符的影響很大,如 a??b 應(yīng)該寫(xiě)作 a ?? b, 因?yàn)?a? 也是一個(gè)有效的操作符.
* a ?? b 返回的是 a unwrap 后的值或 b 的值. ?? 比 js 的 || 好使多了,因?yàn)榍罢吣軠?zhǔn)確區(qū)分零值和nil值.只有nil值時(shí),才需要使用默認(rèn)值.
* names[0..<2] 本質(zhì)上,是得到了一個(gè)數(shù)組. ==> 本質(zhì)上,應(yīng)該是 array 的[]操作符,重載后,支持了 range 參數(shù).
Strings and Characters
* 多行字符串的起始偏移,是根據(jù)末尾的 """ 的偏移 來(lái)判定的.
* collection 類(lèi)型,都有自己的 index struct.String 中涉及的增刪改查操作,適用于所有 collection 類(lèi)型.
* SubString 的增刪改查,只是一個(gè)原有 String 上的游標(biāo)操作.
Collection Types
* collection type 是struct,是復(fù)制傳值,即使只是 a = b
* 操作符重載之后,可以支持?jǐn)?shù)組相加(+)等操作,可以顯著代碼的可讀性和簡(jiǎn)潔性
* 能在編譯器推導(dǎo)出的模板類(lèi)型部分,都可以省略實(shí)例類(lèi)型部分
Control Flow
* switch case 匹配中的 range,也支持源于 String.index 的range
* where 充當(dāng)一個(gè)查詢子句的角色
* \#available的確可以讓API可用性檢查,更方便.
Functions
* 可變字符串的 label 是可以在函數(shù)聲明時(shí),由自己指定的. ==> 可變參數(shù),不需要是最后一組參數(shù)
* inout 有點(diǎn)像是指針傳值;不同的是,在函數(shù)內(nèi)使用時(shí),不需要處理指針解引用操作,直接一個(gè)普通 var 變量使用即可.
* 參數(shù)默認(rèn)是 let 不可變類(lèi)型,不允許修改
Closures
* function type 不包含 label 部分 --> 傳遞function時(shí),其label部分會(huì)被自動(dòng)忽略. --> 在絕大部分場(chǎng)景中,二者是兼容的.
* closure 可以省略參數(shù)類(lèi)型,是因?yàn)轭?lèi)型推導(dǎo)機(jī)制的存在 --> 尾閉包催束,可以省略 ();
* 用作函數(shù)參數(shù)的閉包,如果想在函數(shù)外使用,需要額外加 @escaping 標(biāo)記 ;@autoclosure 會(huì)自動(dòng)補(bǔ)全用作函數(shù)參數(shù)的閉包的{}符號(hào) --> @autoclosure 標(biāo)記的閉包,是有可能和其他一般參數(shù)標(biāo)記的參數(shù),函數(shù)簽名重復(fù)的.
Enumerations
* 遞歸定義的枚舉,就是一個(gè)演示函數(shù)式編程的絕佳示例.
* swift 中的枚舉,變成了一中,可以有效承載數(shù)據(jù)和算法的描述性數(shù)據(jù)結(jié)構(gòu).
* swift 中的 enumeration ,極有可能成為一種新的 Model 載體.
Classes and Structures
* 可選變量,的確會(huì)被自動(dòng)初始化為 nil.
* swift 中,可以設(shè)置組件的 frame 了.呼哈哈 label.frame.origin.x = 100.
* String, Array, and Dictionary 竟然是在swift中被實(shí)現(xiàn)為結(jié)構(gòu)體了,值傳遞.
Properties
* lazy 關(guān)鍵字實(shí)現(xiàn)的屬性懶加載,果然比重寫(xiě) getter 方法,要清晰簡(jiǎn)潔好多啊.
* 可以用 static 或 class 聲明類(lèi)變量/類(lèi)方法; 用class 聲明的類(lèi)變量或類(lèi)方法,支持子類(lèi)重寫(xiě)其實(shí)現(xiàn).
* [self class] 等價(jià)寫(xiě)法是: type(of: self).
Methods
* 結(jié)構(gòu)體實(shí)例中,方法是否能夠修改屬性,也受實(shí)例本身的可變性的影響.
* 結(jié)構(gòu)體或枚舉等值類(lèi)型,允許在實(shí)例方法內(nèi),直接給 self 賦值,完整替換.
* 枚舉類(lèi)型的相關(guān)操作,都可以封裝在枚舉類(lèi)型自身,這樣封裝性會(huì)更好.
Subscripts
* subscript 是一個(gè)新的語(yǔ)言特性,不是簡(jiǎn)單的函數(shù)重寫(xiě).
* subscript 可以接收多個(gè)參數(shù)
* subscript 的參數(shù)和返回值,可以完全自定義
Inheritance
* 可以通過(guò) super 來(lái)使用父類(lèi)方法或?qū)傩?
* 可以在方法或?qū)傩郧凹?final 關(guān)鍵字,來(lái)禁止被子類(lèi)重寫(xiě).
* 可以在類(lèi)前加 final 關(guān)鍵字,來(lái)禁止被繼承.
Initialization
* deisingnated init 一般只調(diào)用父類(lèi) deisingnated init; convenience init 一般只調(diào)用同類(lèi)的 desingnated init;deisingnated init 中,是不允許調(diào)用同級(jí)的另一個(gè)deisingnated init;子類(lèi)中,只允許調(diào)用父類(lèi)的 designated init.
* 調(diào)用父類(lèi)初始化方法前,子類(lèi)自有的 stored property 必須先全部初始化 --> super.init 如果不顯式調(diào)用, 系統(tǒng)會(huì)自動(dòng)調(diào)用. 在調(diào)用 super.init 之前,不能調(diào)用任何實(shí)例方法,因?yàn)閷?duì)象還沒(méi)有效初始化.
* 用 closure 指定默認(rèn)值和屬性的get/set 方法的區(qū)別在于 聲明有個(gè)等號(hào)(=),說(shuō)明前者是個(gè)賦值操作.
Deinitialization
* 把變量置為 nil,即可觸發(fā) deinit.
* deinit 執(zhí)行順序: 子類(lèi) --> 父類(lèi).
* 不能在子類(lèi) deinit 中調(diào)用 super.deinit.
Optional Chaining
* 在訪問(wèn) optional 對(duì)象的內(nèi)部屬性時(shí),必須使用 ? 或 ! 進(jìn)行 unwrap 操作.
* 賦值操作中,如果左側(cè)是要賦值給 optional 實(shí)例的某個(gè)屬性,則會(huì)先 unwrap optional 實(shí)例,如果不為nil,才會(huì)計(jì)算右側(cè)的表達(dá)式.
* 鏈?zhǔn)秸Z(yǔ)法中,有一個(gè) optional 調(diào)用(X?),則返回值必然是 optional 的.
Error Handling
* 函數(shù)A中,可以 try 函數(shù)B,如果函數(shù)B拋出錯(cuò)誤,則會(huì)直接拋給 A 的調(diào)用者.
* do-catch 中的catch 部分 和 switch-case 中的case部分,匹配方式很像.
* try? 的作用是是將函數(shù)返回值轉(zhuǎn)換為 optional 對(duì)象. try? 的返回值,有可能是多層 optional,層數(shù)等于原函數(shù)返回值的 optional wrap 層數(shù) + 1.try! 是保證不會(huì)拋出異常,如果有,就直接crash.
Type Casting
* is 近似于 isKind; 精確判斷時(shí),可以考慮使用 type(of: T1) == T2.self
* 類(lèi)型轉(zhuǎn)換用的是 as? 或 as!,用法習(xí)慣和 try? try! 類(lèi)似.
* 數(shù)組具體化類(lèi)型聲明為 Any / AnyObject 時(shí),數(shù)組內(nèi)可同時(shí)存放多種類(lèi)型不兼容的實(shí)例.
Nested Types
* 支持類(lèi)型嵌套定義,這已經(jīng)是很大的突破了.
* 即使在函數(shù)內(nèi)部,也可以定義新的類(lèi)型.
* 可以用.語(yǔ)法,訪問(wèn)嵌套定義的類(lèi)型.
Extensions
* extensions 和 categories 的重要區(qū)別之一是,前者不需要寫(xiě)名字.
* extensions 不允許覆蓋已有方法,且不同 extentsion 中的方法簽名也不允許重復(fù).
* extentsion 擴(kuò)展的東西,是可以被子類(lèi)繼承的.
Protocols
* 在swift 的設(shè)定中, protocol 也屬于 type,可以用于任何 type 適用的場(chǎng)景.
* 在類(lèi)型聲明遵循某協(xié)議以外的位置,書(shū)寫(xiě)符合協(xié)議的方法是,用 & 連接多個(gè)協(xié)議,如 AP&BP&CP.
* protocol 可以在 extension 中定義自己的方法,任意遵循此協(xié)議的類(lèi)型的實(shí)例都可以調(diào)用此協(xié)議自己的方法實(shí)現(xiàn). --> 可以在 extension 實(shí)現(xiàn)協(xié)議規(guī)定的屬性或方法的默認(rèn)實(shí)現(xiàn). -->可以用 extension-where來(lái)指定,僅在特定條件下,才有效的protocal自有協(xié)議方法.
Generics
* 泛型類(lèi)型中的占位類(lèi)型,也可以用于其自身的 extention 中.
* 可以用類(lèi)似 <T: SomeClass> 或 <T: SomeAProtocol&SomeBProtocol> 或 where 子句 指定占位類(lèi)型本身需要滿足的類(lèi)型或協(xié)議約束. --> 借助 associatedtype 關(guān)鍵字, protocol 也可以支持泛型.
* AnyObject 本身不能直接在類(lèi)型定義時(shí),聲明應(yīng)遵循的協(xié)議的位置使用 --> 可以先定義一個(gè)協(xié)議 A,繼承自 AnyObject,然后讓類(lèi)型定義時(shí)聲明遵循協(xié)議 A,即可間接使用協(xié)議 AnyObject.
Automatic Reference Counting
* optional 變量,也是強(qiáng)引用 -> 可以繼續(xù)使用 weak 關(guān)鍵字聲明弱引用屬性或變量 -> unowned 與 weak 的區(qū)別是,前者不會(huì)自動(dòng)置為 nil.
* closure 是引用類(lèi)型 -> closure 內(nèi)引用實(shí)例屬性,必須加 self前綴 -> closure 的參數(shù)聲明前,可以加一個(gè) capture list,如 [unowned self],來(lái)解決循環(huán)引用問(wèn)題.
* 可以證明,在非 self 以外的情況, closure 并不會(huì)引起內(nèi)部使用變量的引用計(jì)數(shù)的變化.
Memory Safety
* inout 標(biāo)記的函數(shù)參數(shù),是最容易引起訪問(wèn)沖突問(wèn)題的.
* 往同一函數(shù),同時(shí)以不同的 inout 參數(shù),傳遞同一個(gè)實(shí)際變量,會(huì)引起訪問(wèn)沖突 --> 這一行為,可以被自動(dòng)識(shí)別并標(biāo)記出來(lái)
* 類(lèi)型方法調(diào)用,不允許使用自身作為 inout 參數(shù)傳遞給自己的某個(gè)方法.
Access Control
* 默認(rèn)訪問(wèn)級(jí)別是 internal,可以在定義它的模塊內(nèi)的各個(gè)源文件之間自由使用.
* fileprivate 和 private 并存,是因?yàn)閟wift中允許類(lèi)型嵌套定義.
* 子類(lèi)的訪問(wèn)級(jí)別不能比父類(lèi)更寬松;但是子類(lèi)可以通過(guò)重寫(xiě)機(jī)制,使父類(lèi)的成員的訪問(wèn)級(jí)別變的更寬松.
Advanced Operators
* 重載操作符的語(yǔ)法是: static [prefix|infix|postfix] func 某個(gè)操作符 --> == 和 != 也可以重載,來(lái)簡(jiǎn)化等價(jià)判斷操作.
* 復(fù)合操作符,要單獨(dú)重載,不會(huì)自動(dòng)根據(jù)已有操作符自動(dòng)推導(dǎo),如 不會(huì)根據(jù) + ,自動(dòng)實(shí)現(xiàn) +=.
* 可以基于已有操作符,聲明自己的操作符: prefix|infix|postfix operator 操作符,infix 二元操作符,要單獨(dú)聲明優(yōu)先級(jí),如 : infix operator +-: AdditionPrecedence.