Swift 演進(jìn)之路
本篇主要是對(duì)[《A站 的 Swift 實(shí)踐》](https://ming1016.github.io/2021/05/22/acfun-swift-practice/)文章中的一幅配圖做了詳細(xì)的擴(kuò)展,能夠更加全面和詳細(xì)了解 Swift 語言的發(fā)展,文章中提到的 Swift 各版本的語法示例代碼,及本文內(nèi)容都可以在 [Swift 小冊(cè)子](https://github.com/KwaiAppTeam/SwiftPamphletApp)里對(duì)應(yīng)欄目里找到,這個(gè)假期我也對(duì) Swift 小冊(cè)子里欄目?jī)?nèi)容進(jìn)行了些更新和補(bǔ)充。《A站 的 Swift 實(shí)踐》文章的那個(gè)演進(jìn)配圖如下:

文章內(nèi)容如下:
Swift 1.1
?countElements() 改成了 count()。
?@NSApplicationMain 可以在 macOS 上使用。
Swift 1.2
?引入 Set 類型。
?if let 可以放到一起,使用逗號(hào)分隔。
?新增 zip() 和 flatMap()。
?類增加靜態(tài)方法和靜態(tài)屬性,使用 static 關(guān)鍵字描述。
?as! 用于類型強(qiáng)轉(zhuǎn),失敗會(huì)崩潰。
?@noescape 用于描述作為參數(shù)閉包,用來告訴 Swift 閉包將在函數(shù)返回前使用。
?常量可以延后初始化。
Swift 2.0
?增加 guard 關(guān)鍵字,用于解可選項(xiàng)值。
?defer 關(guān)鍵字用來延遲執(zhí)行,即使拋出錯(cuò)誤了都會(huì)在最后執(zhí)行。
?ErrorType 協(xié)議,以及 throws、do、try 和 catch 的引入用來處理錯(cuò)誤。
?characters 加上 count,用來替代 count()。
?#available 用來檢查系統(tǒng)版本。
Swift 2.1
?字符串插值可以包含字符串字面符號(hào)。
Swift 2.2
?__FILE__, __LINE__ 和 __FUNCTION__ 換成 #file,#line 和 #function。
?廢棄 ++ 和 -- 操作符。
?C 語言風(fēng)格 for 循環(huán)廢棄。
?廢棄變量參數(shù),因?yàn)樽兞繀?shù)容易和 inout 搞混。
?廢棄字符串化的選擇器,選擇器不再能寫成字符串了。
?元組可直接比較是否相等。
Swift 3.0
?規(guī)范動(dòng)詞和名詞來命名。
?去掉 NS 前綴。
?方法名描述參數(shù)部分變?yōu)閰?shù)名。
?省略沒必要的單詞,命名做了簡(jiǎn)化呢。比如 stringByTrimmingCharactersInSet 就換成了 trimmingCharacters。
?枚舉的屬性使用小寫開頭。
?引入 C 函數(shù)的屬性。
Swift 3.1
?序列新增 prefix(while:) 和 drop(while:) 方法,順序遍歷執(zhí)行閉包里的邏輯判斷,滿足條件就返回,遇到不匹配就會(huì)停止遍歷。prefix 返回滿足條件的元素集合,drop 返回停止遍歷之后那些元素集合。
?泛型適用于嵌套類型。
?類型的擴(kuò)展可以使用約束條件,比如擴(kuò)展數(shù)組時(shí),加上元素為整數(shù)的約束,這樣的擴(kuò)展就只會(huì)對(duì)元素為整數(shù)的數(shù)組有效。
Swift 4.0
?加入 Codable 協(xié)議,更 Swifty 的編碼和解碼。提案 [SE-0167 Swift Encoders](https://github.com/apple/swift-evolution/blob/master/proposals/0167-swift-encoders.md)
?字符串加入三個(gè)雙引號(hào)的支持,讓多行字符串編寫更加直觀。提案 [SE-0168 Multi-Line String Literals](https://github.com/apple/swift-evolution/blob/master/proposals/0168-multi-line-string-literals.md)
?字符串變成集合,表示可以對(duì)字符串進(jìn)行逐字遍歷、map 和反轉(zhuǎn)等操作。
?keypaths 語法提升。提案見 [SE-0161 Smart KeyPaths: Better Key-Value Coding for Swift](https://github.com/apple/swift-evolution/blob/master/proposals/0161-key-paths.md)
?集合加入 ..<10 這樣語法的單邊切片。提案 [SE-0172 One-sided Ranges](https://github.com/apple/swift-evolution/blob/master/proposals/0172-one-sided-ranges.md)
?字典新增 mapValues,可 map 字典的值。通過 grouping 可對(duì)字典進(jìn)行分組生成新字典,鍵和值都可以。從字典中取值,如果鍵對(duì)應(yīng)無值,則使用通過 default 指定的默認(rèn)值。提案 [SE-0165 Dictionary & Set Enhancements](https://github.com/apple/swift-evolution/blob/master/proposals/0165-dict.md)
Swift 4.1
?Hashable 也不需要返回一個(gè)唯一的 hashValue 哈希值屬性。
?Equatable 和 Hashable 自動(dòng)合成的提案參見 [SE-0185 Synthesizing Equatable and Hashable conformance](https://github.com/apple/swift-evolution/blob/master/proposals/0185-synthesize-equatable-hashable.md)。
?兩個(gè)自定類型比較是否相等時(shí),不再需要比較每個(gè)屬性,Swift 會(huì)自動(dòng)生成 == 方法,你只需要聲明 Equatable 協(xié)議。
?引入 KeyDecodingStrategy屬性,其中 .convertFromSnakeCase 可以將下劃線的命名轉(zhuǎn)化成駝峰的命名。
?引入條件符合性,只有滿足一定條件才符合協(xié)議。比如擴(kuò)展數(shù)組要求當(dāng)里面元素滿足某協(xié)議數(shù)組才符合這個(gè)協(xié)議。提案見 [SE-0143 Conditional conformances](https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md)。
?引入 canImport 宏條件關(guān)鍵字,判斷是否可以使用某庫,以前只能通過判斷操作系統(tǒng)平臺(tái)來判斷。提案見 [SE-0075 Adding a Build Configuration Import Test](https://github.com/apple/swift-evolution/blob/master/proposals/0075-import-test.md)。
?新增能夠去除為零項(xiàng)目的 compactMap()。提案 [SE-0187 Introduce Sequence.compactMap(_:)](https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.md)
?關(guān)聯(lián)類型可以創(chuàng)建遞歸約束,提案見 [SE-0157 Support recursive constraints on associated types](https://github.com/apple/swift-evolution/blob/master/proposals/0157-recursive-protocol-constraints.md)
?targetEnvironment 環(huán)境的判斷,比如模擬器。提案見 [SE-0190 Target environment platform condition](https://github.com/apple/swift-evolution/blob/master/proposals/0190-target-environment-platform-condition.md) 。
Swift 4.2
?新增動(dòng)態(tài)成員查詢,@dynamicMemberLookup 新屬性,指示訪問屬性時(shí)調(diào)用一個(gè)已實(shí)現(xiàn)的處理動(dòng)態(tài)查找的下標(biāo)方法 subscript(dynamicMemeber:),通過指定屬性字符串名返回值。提案 [SE-0195 Introduce User-defined "Dynamic Member Lookup" Types](https://github.com/apple/swift-evolution/blob/master/proposals/0195-dynamic-member-lookup.md)
?集合新加 removeAll(where:) 方法,過濾滿足條件所有元素。比 filter 更高效。提案 [SE-0197 Adding in-place removeAll(where:) to the Standard Library](https://github.com/apple/swift-evolution/blob/master/proposals/0197-remove-where.md)
?布爾值增加 toggle() 方法,用來切換布爾值。提案見 [SE-0199 Adding toggle to Bool](https://github.com/apple/swift-evolution/blob/master/proposals/0199-bool-toggle.md)
?引入 CaseIterable 協(xié)議,可以將枚舉中所有 case 生成 allCases 數(shù)組。提案 [SE-0194 Derived Collection of Enum Cases](https://github.com/apple/swift-evolution/blob/master/proposals/0194-derived-collection-of-enum-cases.md)
?引入 #warning 和 #error 兩個(gè)新的編譯器指令。#warning 會(huì)產(chǎn)生一個(gè)警告,#error 會(huì)直接讓編譯出錯(cuò)。比如必須要填寫 token 才能編譯的話可以在設(shè)置 token 的代碼前加上 #error 和說明。提案見 [SE-0196 Compiler Diagnostic Directives](https://github.com/apple/swift-evolution/blob/master/proposals/0196-diagnostic-directives.md)
?新增加密安全的隨機(jī) API。直接在數(shù)字類型上調(diào)用 random() 方法生成隨機(jī)數(shù)。shuffle() 方法可以對(duì)數(shù)組進(jìn)行亂序重排。提案 [SE-0202 Random Unification](https://github.com/apple/swift-evolution/blob/master/proposals/0202-random-unification.md)
?更簡(jiǎn)單更安全的哈希協(xié)議,引入新的 Hasher 結(jié)構(gòu),通過 combine() 方法為哈希值添加更多屬性,調(diào)用 finalize() 方法生成最終哈希值。提案 [SE-0206 Hashable Enhancements](https://github.com/apple/swift-evolution/blob/master/proposals/0206-hashable-enhancements.md)
?集合增加 allSatisfy() 用來判斷集合中的元素是否都滿足了一個(gè)條件。提案 [SE-0207 Add an allSatisfy algorithm to Sequence](https://github.com/apple/swift-evolution/blob/master/proposals/0207-containsOnly.md)
Swift 5.0
?@dynamicCallable 動(dòng)態(tài)可調(diào)用類型。通過實(shí)現(xiàn) dynamicallyCall 方法來定義變參的處理。提案 [SE-0216 Introduce user-defined dynamically "callable" types](https://github.com/apple/swift-evolution/blob/master/proposals/0216-dynamic-callable.md)
?新加 Result 類型用來處理錯(cuò)誤。提案 [SE-0235 Add Result to the Standard Library](https://github.com/apple/swift-evolution/blob/master/proposals/0235-add-result.md)
?新增原始字符串能力,在字符串前加上一個(gè)或多個(gè)#符號(hào)。里面的雙引號(hào)和轉(zhuǎn)義符號(hào)將不再起作用了,如果想讓轉(zhuǎn)義符起作用,需要在轉(zhuǎn)義符后面加上#符號(hào)。提案見 [SE-0200 Enhancing String Literals Delimiters to Support Raw Text](https://github.com/apple/swift-evolution/blob/master/proposals/0200-raw-string-escaping.md)
?自定義字符串插值。提案 [SE-0228 Fix ExpressibleByStringInterpolation](https://github.com/apple/swift-evolution/blob/master/proposals/0228-fix-expressiblebystringinterpolation.md)
?枚舉新增 @unknown 用來區(qū)分固定的枚舉和可能改變的枚舉的能力。用于防止未來新增枚舉屬性會(huì)進(jìn)行提醒提示完善每個(gè) case 的處理。提案 [SE-0192 Handling Future Enum Cases](https://github.com/apple/swift-evolution/blob/master/proposals/0192-non-exhaustive-enums.md)
?compactMapValues() 對(duì)字典值進(jìn)行轉(zhuǎn)換和解包。可以解可選類型,并去掉 nil 值。提案 [SE-0218 Introduce compactMapValues to Dictionary](https://github.com/apple/swift-evolution/blob/master/proposals/0218-introduce-compact-map-values.md)
?扁平化 try?。提案 [SE-0230 Flatten nested optionals resulting from 'try?'](https://github.com/apple/swift-evolution/blob/master/proposals/0230-flatten-optional-try.md)
?isMultiple(of:) 方法檢查一個(gè)數(shù)字是否是另一個(gè)數(shù)字的倍數(shù)。提案見 [SE-0225 Adding isMultiple to BinaryInteger](https://github.com/apple/swift-evolution/blob/master/proposals/0225-binaryinteger-iseven-isodd-ismultiple.md)
Swift 5.1
?有序集合的 diff,通過 difference(from:) 方法,可以返回要?jiǎng)h除哪些和添加哪些項(xiàng)目能夠讓兩個(gè)集合相等。提案 [SE-0240 Ordered Collection Diffing](https://github.com/apple/swift-evolution/blob/master/proposals/0240-ordered-collection-diffing.md)
?屬性包裝。提案 [SE-0258 Property Wrappers](https://github.com/apple/swift-evolution/blob/main/proposals/0258-property-wrappers.md)
?不透明返回類型。函數(shù)調(diào)用者決定返回什么類型是泛型,函數(shù)自身決定返回什么類型使用不透明返回類型。提案 [SE-0244 Opaque Result Types](https://github.com/apple/swift-evolution/blob/master/proposals/0244-opaque-result-types.md)
?初始化有默認(rèn)值的屬性可不設(shè)置。提案 [SE-0242 Synthesize default values for the memberwise initializer](https://github.com/apple/swift-evolution/blob/master/proposals/0242-default-values-memberwise.md)
?單行表達(dá)式函數(shù)隱式返回,返回一個(gè)單行表達(dá)式的函數(shù)可以不用 return 關(guān)鍵字。提案 [SE-0255 Implicit returns from single-expression functions](https://github.com/apple/swift-evolution/blob/master/proposals/0255-omit-return.md)
?在類、結(jié)構(gòu)體和枚舉里使用 Self,Self 可以指代包含的類型。提案見 [SE-0068 Expanding Swift Self to class members and value types](https://github.com/apple/swift-evolution/blob/master/proposals/0068-universal-self.md)
?靜態(tài)下標(biāo)。提案 [SE-0254 Static and class subscripts](https://github.com/apple/swift-evolution/blob/master/proposals/0254-static-subscripts.md)
?枚舉里有 none 的 case 編譯器會(huì)提示換成 Optional.none。
?引入未初始化數(shù)組。提案 [SE-0245 Add an Array Initializer with Access to Uninitialized Storage](https://github.com/apple/swift-evolution/blob/master/proposals/0245-array-uninitialized-initializer.md)
Swift 5.2
?自定義類型中實(shí)現(xiàn)了 callAsFunction() 的話,該類型的值就可以直接調(diào)用。提案 [SE-0253 Callable values of user-defined nominal types](https://github.com/apple/swift-evolution/blob/master/proposals/0253-callable.md)
?鍵路徑表達(dá)式作為函數(shù)。提案 [SE-0249 Key Path Expressions as Functions](https://github.com/apple/swift-evolution/blob/master/proposals/0249-key-path-literal-function-expressions.md)
Swift 5.3
?SPM 包管理資源,SPM 可以包含資源文件,比如多媒體或文本等。通過 Bundle.module 訪問這些資源。提案 [SE-0271 Package Manager Resources](https://github.com/apple/swift-evolution/blob/master/proposals/0271-package-manager-resources.md)
?SPM 包里資源本地化。提案 [SE-0278 Package Manager Localized Resources](https://github.com/apple/swift-evolution/blob/master/proposals/0278-package-manager-localized-resources.md)
?SPM 可以整合二進(jìn)制包依賴。提案 [SE-0272 Package Manager Binary Dependencies](https://github.com/apple/swift-evolution/blob/master/proposals/0272-swiftpm-binary-dependencies.md)
?SPM 可以設(shè)置特定平臺(tái)的依賴。提案 [SE-0273 Package Manager Conditional Target Dependencies](https://github.com/apple/swift-evolution/blob/master/proposals/0273-swiftpm-conditional-target-dependencies.md)
?單個(gè) catch 塊中捕獲多個(gè) Error 的 case。提案 [SE-0276 Multi-Pattern Catch Clauses](https://github.com/apple/swift-evolution/blob/master/proposals/0276-multi-pattern-catch-clauses.md)
?支持多個(gè)尾部閉包。提案見 [SE-0279 Multiple Trailing Closures](https://github.com/apple/swift-evolution/blob/master/proposals/0279-multiple-trailing-closures.md)
?符合 Comparable 協(xié)議的枚舉可以進(jìn)行比較。提案 [SE-0266 Synthesized Comparable conformance for enum types](https://github.com/apple/swift-evolution/blob/master/proposals/0266-synthesized-comparable-for-enumerations.md)
?很多地方可以不用加 self 來指代實(shí)例自己了。提案見 [SE-0269 Increase availability of implicit self in @escaping closures when reference cycles are unlikely to occur](https://github.com/apple/swift-evolution/blob/master/proposals/0269-implicit-self-explicit-capture.md)
?@main 可以方便指定程序入口點(diǎn)。提案 [SE-0281 @main: Type-Based Program Entry Points](https://github.com/apple/swift-evolution/blob/master/proposals/0281-main-attribute.md)
?where 子句可以用到泛型和擴(kuò)展函數(shù)中。提案 [SE-0267 where clauses on contextually generic declarations](https://github.com/apple/swift-evolution/blob/master/proposals/0267-where-on-contextually-generic.md)
?枚舉的 case 也可以符合協(xié)議。提案 [SE-0280 Enum cases as protocol witnesses](https://github.com/apple/swift-evolution/blob/master/proposals/0280-enum-cases-as-protocol-witnesses.md)
?完善 didSet,性能提升。提案 [SE-0268 Refine didSet Semantics](https://github.com/apple/swift-evolution/blob/master/proposals/0268-didset-semantics.md)
?新增 Float16 類型,即半精度浮點(diǎn)類型。提案 [SE-0277 Float16](https://github.com/apple/swift-evolution/blob/master/proposals/0277-float16.md)
Swift 5.4
?SPM 支持 @main。提案見 [SE-0294 Declaring executable targets in Package Manifests](https://github.com/apple/swift-evolution/blob/main/proposals/0294-package-executable-targets.md)
?結(jié)果生成器(Result builders),通過傳遞序列創(chuàng)建新值,SwiftUI就是使用的結(jié)果生成器將多個(gè)視圖生成一個(gè)視圖。提案 [SE-0289 Result builders](https://github.com/apple/swift-evolution/blob/main/proposals/0289-result-builders.md)
?增強(qiáng)隱式成員語法,即使用了隱式的成員可以進(jìn)行鏈?zhǔn)教幚怼L岚敢?[SE-0287 Extend implicit member syntax to cover chains of member references](https://github.com/apple/swift-evolution/blob/main/proposals/0287-implicit-member-chains.md)
?函數(shù)開始有了使用多個(gè)變量參數(shù)的能力。提案 [SE-0284 Allow Multiple Variadic Parameters in Functions, Subscripts, and Initializers](https://github.com/apple/swift-evolution/blob/main/proposals/0284-multiple-variadic-parameters.md)
?嵌套函數(shù)可以重載,嵌套函數(shù)可以在聲明函數(shù)之前調(diào)用他。
?屬性包裝支持局部變量。
Swift 5.5
?Async await,用同步寫法來處理異步。提案 [SE-0296 Async/await](https://github.com/apple/swift-evolution/blob/main/proposals/0296-async-await.md)
?Async sequences,異步序列上的循環(huán)能力。符合 AsyncSequence 協(xié)議的序列可以通過 for await 來進(jìn)行異步循環(huán)。提案見 [SE-0298 Async/Await: Sequences](https://github.com/apple/swift-evolution/blob/main/proposals/0298-asyncsequence.md)?
?結(jié)構(gòu)化的并發(fā),使用 Task 和 TaskGroup 執(zhí)行、取消和監(jiān)聽當(dāng)前操作的方法。復(fù)雜的并發(fā)處理可以使用 withTaskGroup() 來創(chuàng)建一組 Task,addTask() 用來添加任務(wù),cancelAll() 可以取消任務(wù),addTask() 在取消任務(wù)后可以繼續(xù)添加任務(wù),如果使用了 addTaskUnlessCancelled() 方法就可以避免取消后會(huì)繼續(xù)添加任務(wù)這種情況。提案見 [SE-0304 Structured concurrency](https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md)
?只讀屬性支持 async 和 throws 關(guān)鍵字。提案 [SE-0310 Effectful Read-only Properties](https://github.com/apple/swift-evolution/blob/main/proposals/0310-effectful-readonly-properties.md)
?async let,可以創(chuàng)建 await 子任務(wù)。提案 [SE-0317 async let bindings](https://github.com/apple/swift-evolution/blob/main/proposals/0317-async-let.md)
?以前異步代碼的適配。比如 DispatchQueue.main.async,外部庫可以通過 withCheckedContinuation() 函數(shù)來對(duì)以前異步代碼進(jìn)行封裝。提案見 [SE-0300 Continuations for interfacing async tasks with synchronous code](https://github.com/apple/swift-evolution/blob/main/proposals/0300-continuation.md)
?Actor,可以確保內(nèi)部只能被一個(gè)線程訪問,避免存儲(chǔ)屬性和方法出現(xiàn)競(jìng)爭(zhēng)條件。提案在這 [SE-0306 Actors](https://github.com/apple/swift-evolution/blob/main/proposals/0306-actors.md)
?全局 actors,通過 actor 將全局狀態(tài)隔離出來,避免數(shù)據(jù)競(jìng)爭(zhēng)。比如主線程 @MainActor 這個(gè)屬性包裝可以將屬性和方法標(biāo)記為只能在主線程上訪問。提案 [SE-0316 Global actors](https://github.com/apple/swift-evolution/blob/main/proposals/0316-global-actors.md)
?Sendable 協(xié)議和 @Sendable 屬性包裝,目的是支持安全的將數(shù)據(jù)從一個(gè)線程傳給另一個(gè)線程。Swift 的核心數(shù)據(jù)類型比如字符、集合等已符合 Sendable 協(xié)議。提案 [SE-0302 Sendable and @Sendable closures](https://github.com/apple/swift-evolution/blob/main/proposals/0302-concurrent-value-and-concurrent-closures.md)
?局部變量可以使用 lazy。
?屬性包裝可以用到函數(shù)和閉包參數(shù)上。提案[SE-0293 Extend Property Wrappers to Function and Closure Parameters](https://github.com/apple/swift-evolution/blob/main/proposals/0293-extend-property-wrappers-to-function-and-closure-parameters.md)
?泛型支持靜態(tài)成員查找。提案 [SE-0299 Extending Static Member Lookup in Generic Contexts](https://github.com/apple/swift-evolution/blob/main/proposals/0299-extend-generic-static-member-lookup.md)
?#if 用于后綴成員表達(dá)式。提案見 [SE-0308 #if for postfix member expressions](https://github.com/apple/swift-evolution/blob/main/proposals/0308-postfix-if-config-expressions.md)
?CGFloat 和 Double 之間可以隱式轉(zhuǎn)換。提案 [SE-0307 Allow interchangeable use of CGFloat and Double types](https://github.com/apple/swift-evolution/blob/main/proposals/0307-allow-interchangeable-use-of-double-cgfloat-types.md)
?Codable 支持關(guān)聯(lián)值枚舉。提案 [SE-0295 Codable synthesis for enums with associated values](https://github.com/apple/swift-evolution/blob/main/proposals/0295-codable-synthesis-for-enums-with-associated-values.md)
上面各個(gè)版本的語法更新的內(nèi)容和更多代碼的示例都可以在 Swift 小冊(cè)子里查看,內(nèi)容力求更全,描述力求更簡(jiǎn)潔,more big, more small。不想下載 app 也可以查看[《戴銘的 Swift 小冊(cè)子4.0》](https://ming1016.github.io/2021/11/23/daiming-swift-pamphlet/)這篇,內(nèi)容也同步做了更新和補(bǔ)充。我對(duì)小冊(cè)子內(nèi)容查看樣式視覺做了更新,排版用了赫蹏(hètí),字體是霞鶩文楷,更新了代碼高亮風(fēng)格,內(nèi)容看起來更舒服。還有 icon 也進(jìn)行替換,不用再對(duì)著枯燥的 SFSymbol 和我先前臨時(shí)從以前圖里隨便挑的那條小狗 App icon 看了。


另
小冊(cè)子現(xiàn)在可以直接下載 dmg 使用了,4.1下載地址:[戴銘的Swift小冊(cè)子4.1.dmg.zip](https://github.com/KwaiAppTeam/SwiftPamphletApp/files/8040117/Swift.4.1.dmg.zip)

