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