Swift 5.5 新特性搶先看,async/await 將重磅來襲
作者丨小集
來源丨知識小集(ID:zsxjtip)
再過一周的時間,WWDC21 就正式舉行了,如果不出意外的話,Swift 5.5 測試版也會在期間發(fā)布。早在 3 月 13 日,官方論壇就公布了 Swift 5.5 版本的發(fā)布計劃,并在 4 月 16 日拉出了 release/5.5 分支。經(jīng)過幾個月時間的準(zhǔn)備,從 Swift Evolution 中,我們能發(fā)現(xiàn) Swift 5.5 將為我們帶來許多期待已久的特性,如 async/await。我們今天就來簡單整理一下這些 可能 將在 Swift 5.5 中出現(xiàn)的新特性。
SE-0291 包集合

這個 proposal 旨在為 SwiftPM 添加對包集合的支持。包集合是包和相關(guān)元數(shù)據(jù)的列表,可以更輕松地發(fā)現(xiàn)特定用例的現(xiàn)有包。SwiftPM 將允許用戶訂閱這些集合,通過 swift package-collection 命令行界面搜索它們,并使 libSwiftPM 的任何客戶端都可以訪問它們的內(nèi)容。這個 proposal 關(guān)注于以命令行界面和包集合想著的配置數(shù)據(jù)格式。
例如,list 命令將列出用戶配置的所有集合:
$ swift package-collection list [--json]
My organisation's packages - https://example.com/packages.json
...
describe 命令顯示來自包本身的元數(shù)據(jù)。
$ swift package-collection describe [--json] https://github.com/jpsim/yams
Description: A sweet and swifty YAML parser built on LibYAML.
Available Versions: 4.0.0, 3.0.0, ...
Watchers: 14
Readme: https://github.com/jpsim/Yams/blob/master/README.md
Authors: @norio-nomura, @jpsim
--------------------------------------------------------------
Latest Version: 4.0.0
Package Name: Yams
Modules: Yams, CYaml
Supported Platforms: iOS, macOS, Linux, tvOS, watchOS
Supported Swift Versions: 5.3, 5.2, 5.1, 5.0
License: MIT
CVEs: ...
https://github.com/apple/swift-evolution/blob/main/proposals/0291-package-collections.md
SE-0293 將屬性包裝器擴展到函數(shù)和閉包參數(shù)

Property Wrappers 用于抽象出常見的屬性訪問器模式,在 Swift 5.1 中引入。不過之前僅允許在局部變量和類型屬性上應(yīng)用屬性包裝器。而這個 proposal 的目標(biāo)是將屬性包裝器擴展到函數(shù)和閉包參數(shù)。
例如,使用來自 PropertyKit 的驗證,我們可以將各種前提條件抽象到一個屬性包裝器中:
@propertyWrapper
struct Asserted<Value> {
init(
wrappedValue: Value,
validation: Validation<Value>,
) { ... }
var wrappedValue: Value { ... }
}
將 @Asserted 應(yīng)用于參數(shù)以對參數(shù)值斷言某些先決條件會很有用。例如,下面的代碼斷言傳遞給 quantity 參數(shù)的參數(shù)大于或等于1:
func buy(
@Asserted(.greaterOrEqual(1)) quantity: Int,
of product: Product,
) { ... }
https://github.com/apple/swift-evolution/blob/main/proposals/0293-extend-property-wrappers-to-function-and-closure-parameters.md
SE-0295 有關(guān)聯(lián)值的枚舉的 Codable 合成

在 SE-0166 中引入了 Codable,它支持合成類和結(jié)構(gòu)類型的 Encodable 和 Decodable 一致性,其中僅包含也符合各自協(xié)議的值。
這個 proposal 將擴展對枚舉關(guān)聯(lián)值的一致性的自動合成的支持。
如以下枚舉有關(guān)聯(lián)值:
enum Command: Codable {
case load(key: String)
case store(key: String, value: Int)
}
將會被編碼為
{
"load": {
"key": "MyKey"
}
}
{
"store": {
"key": "MyKey",
"value": 42
}
}
編譯器將生成以下 CodingKeys 聲明:
// contains keys for all cases of the enum
enum CodingKeys: CodingKey {
case load
case store
}
// contains keys for all associated values of `case load`
enum LoadCodingKeys: CodingKey {
case key
}
// contains keys for all associated values of `case store`
enum StoreCodingKeys: CodingKey {
case key
case value
}
https://github.com/apple/swift-evolution/blob/main/proposals/0295-codable-synthesis-for-enums-with-associated-values.md
SE-0296 async/await

現(xiàn)代 Swift 開發(fā)涉及大量使用閉包和完成處理程序的異步編程,但這些 API 都很難使用。當(dāng)使用許多異步操作、錯誤處理或異步調(diào)用之間的控制流變得復(fù)雜時,會讓問題變得很復(fù)雜。我們先看一個簡單的例子:
// 一系列簡單的異步操作通常需要深度嵌套的閉包
func processImageData1(completionBlock: (_ result: Image) -> Void) {
loadWebResource("dataprofile.txt") { dataResource in
loadWebResource("imagedata.dat") { imageResource in
decodeImage(dataResource, imageResource) { imageTmp in
dewarpAndCleanupImage(imageTmp) { imageResult in
completionBlock(imageResult)
}
}
}
}
}
processImageData1 { image in
display(image)
}
而這個提案則引入了一種語言擴展,大大簡化了這些操作,讓代碼更加自然而不易出錯。這種設(shè)計為 Swift 引入了一個協(xié)程模型。函數(shù)可以是 async,允許程序員使用正常的控制流機制編寫涉及異步操作的復(fù)雜邏輯。編譯器負(fù)責(zé)將異步函數(shù)轉(zhuǎn)換為一組合適的閉包和狀態(tài)機。實際上 async/await 語義早已是現(xiàn)代編程語言的標(biāo)配。我們來看看,async/await 如何讓代碼變得更加簡潔:
func loadWebResource(_ path: String) async throws -> Resource
func decodeImage(_ r1: Resource, _ r2: Resource) async throws -> Image
func dewarpAndCleanupImage(_ i : Image) async throws -> Image
func processImageData() async throws -> Image {
let dataResource = try await loadWebResource("dataprofile.txt")
let imageResource = try await loadWebResource("imagedata.dat")
let imageTmp = try await decodeImage(dataResource, imageResource)
let imageResult = try await dewarpAndCleanupImage(imageTmp)
return imageResult
}
不過,這個 proposal 并不提供并發(fā),結(jié)構(gòu)化并發(fā)問題由另一個 proposal 引入,它將異步函數(shù)與并發(fā)執(zhí)行的任務(wù)相關(guān)聯(lián),并提供用于創(chuàng)建、查詢和取消任務(wù)的 API。
https://github.com/apple/swift-evolution/blob/main/proposals/0296-async-await.md
SE-0297 與 Objective-C 的并發(fā)互操作性

在 Apple 平臺上,Swift 與 Objective-C 的混編與交互目前來講還是一個很大的課題。在 Objective-C 中,異步 API 隨處可見,在 iOS 14.0 SDK 中就包含了近 1000 個接受 completion 處理器的方法。例如以下 PassKit API 中的方法
- (void)signData:(NSData *)signData
withSecureElementPass:(PKSecureElementPass *)secureElementPass
completion:(void (^)(NSData *signedData, NSData *signature, NSError *error))completion;
這些方法包括可以直接在 Swift 中調(diào)用的方法,可以在 Swift 定義的子類中覆蓋的方法,以及可以實現(xiàn)的協(xié)議中的方法。
當(dāng)前,以上 Objective-C 函數(shù)在 Swift 中會被翻譯成以下函數(shù):
@objc func sign(_ signData: Data,
using secureElementPass: PKSecureElementPass,
completion: @escaping (Data?, Data?, Error?) -> Void
)
這個 proposal 旨在為 Swift 并發(fā)結(jié)構(gòu)與 Objective-C 之間提供互操作性,并實現(xiàn)以下目標(biāo):
將 Objective-C 完成處理程序方法轉(zhuǎn)換為 Swift 中的
async方法;允許將 Swift 中定義的
async方法標(biāo)記為@objc,在這種情況下,它們將作為完成處理程序方法導(dǎo)出;提供 Objective-C 屬性來控制如何將基于完成處理程序的 API 轉(zhuǎn)換為
asyncSwift 函數(shù)。
基于這些假設(shè),以上 Objective-C 函數(shù)將會被翻譯為以下 async 函數(shù):
@objc func sign(
_ signData: Data,
using secureElementPass: PKSecureElementPass
) async throws -> (Data, Data)
同時可以通過以下方式來調(diào)用:
let (signedValue, signature) = try await passLibrary.sign(signData, using: pass)
https://github.com/apple/swift-evolution/blob/main/proposals/0297-concurrency-objc.md
SE-0298 Async/Await: 序列

SE-0296 的 async/await 特性為 Swift 提供了更直觀的異步編程方式。而這個 proposal 的目標(biāo)是基于 async/await,以內(nèi)置的方式更直觀地編寫和使用隨時間返回多個值的函數(shù)。
這個 proposal 主要由三個部分組成:
表示異步值序列的協(xié)議的標(biāo)準(zhǔn)庫定義;
編譯器支持在異步值序列上使用 for...in 語法;
對異步值序列進行操作的常用函數(shù)的標(biāo)準(zhǔn)庫實現(xiàn)
基于這個 proposal,迭代異步值序列像迭代同步值序列一樣簡單。一個示例用例是迭代文件中的行,如下所示:
for try await line in myFile.lines() {
// Do something with each line
}
為此,標(biāo)準(zhǔn)庫中定義了以下協(xié)議
public protocol AsyncSequence {
associatedtype AsyncIterator: AsyncIteratorProtocol where AsyncIterator.Element == Element
associatedtype Element
__consuming func makeAsyncIterator() -> AsyncIterator
}
public protocol AsyncIteratorProtocol {
associatedtype Element
mutating func next() async throws -> Element?
}
編譯器生成的代碼將允許在符合 AsyncSequence 的任何類型上使用for in循環(huán)。標(biāo)準(zhǔn)庫還將擴展協(xié)議以提供熟悉的通用算法。如以下示例:
struct Counter : AsyncSequence {
let howHigh: Int
struct AsyncIterator : AsyncIteratorProtocol {
let howHigh: Int
var current = 1
mutating func next() async -> Int? {
// We could use the `Task` API to check for cancellation here and return early.
guard current <= howHigh else {
return nil
}
let result = current
current += 1
return result
}
}
func makeAsyncIterator() -> AsyncIterator {
return AsyncIterator(howHigh: howHigh)
}
}
在調(diào)用端,則可以如下使用:
for await i in Counter(howHigh: 3) {
print(i)
}
/*
Prints the following, and finishes the loop:
1
2
3
*/
for await i in Counter(howHigh: 3) {
print(i)
if i == 2 { break }
}
/*
Prints the following:
1
2
*/
https://github.com/apple/swift-evolution/blob/main/proposals/0298-asyncsequence.md
SE-0299 在通用上下文中擴展靜態(tài)成員查找

Swift 支持對具體類型的靜態(tài)成員查找,并通過類似枚舉的 . 語法來調(diào)用。例如,SwiftUI 中使用預(yù)定義的常用值作為靜態(tài)屬性擴展了 Font 和 Color 等類型。
extension Font {
public static let headline: Font
public static let subheadline: Font
public static let body: Font
...
}
extension Color {
public static let red: Color
public static let green: Color
public static let blue: Color
...
}
可通過以下方式來調(diào)用:
VStack {
Text(item.title)
.font(.headline)
.foregroundColor(.primary)
Text(item.subtitle)
.font(.subheadline)
.foregroundColor(.secondary)
}
不過,靜態(tài)成員查找目前存在一個問題:不支持泛型函數(shù)中的協(xié)議成員,所以沒有辦法使用 . 語法來調(diào)用,如 SwiftUI 定義了一個 toggleStyle 視圖裝飾器:
extension View {
public func toggleStyle<S: ToggleStyle>(_ style: S) -> some View
}
public protocol ToggleStyle {
associatedtype Body: View
func makeBody(configuration: Configuration) -> Body
}
public struct DefaultToggleStyle: ToggleStyle { ... }
public struct SwitchToggleStyle: ToggleStyle { ... }
public struct CheckboxToggleStyle: ToggleStyle { ... }
目前的調(diào)用方式是,在使用 toggleStyle 修飾符時將具體類型以全名方式寫入 ToggleStyle:
Toggle("Wi-Fi", isOn: $isWiFiEnabled)
.toggleStyle(SwitchToggleStyle())
而這個 proposal 的目標(biāo)是放寬對協(xié)議上訪問靜態(tài)成員的限制,讓泛型 API 具有更好的可讀性,即通過以下方式來調(diào)用:
Toggle("Wi-Fi", isOn: $isWiFiEnabled)
.toggleStyle(.switch)
https://github.com/apple/swift-evolution/blob/main/proposals/0299-extend-generic-static-member-lookup.md
SE-0300 異步任務(wù)與同步代碼接口

異步 Swift 代碼需要能夠與使用諸如完成回調(diào)和委托方法之類的技術(shù)的現(xiàn)有同步代碼一起工作以響應(yīng)事件。異步任務(wù)可以將自己暫停,然后同步代碼可以捕獲并調(diào)用它們以響應(yīng)事件來恢復(fù)任務(wù)。
標(biāo)準(zhǔn)庫將提供 API 來獲取當(dāng)前異步任務(wù)的延續(xù),這會掛起任務(wù),并產(chǎn)生一個值,同步代碼隨后可以通過該值使用句柄來恢復(fù)任務(wù)。例如
func beginOperation(completion: (OperationResult) -> Void)
我們可以通過掛起任務(wù)并在調(diào)用回調(diào)時使用其連續(xù)性將其恢復(fù)為異步接口,然后將傳遞給回調(diào)的參數(shù)轉(zhuǎn)換為異步函數(shù)的正常返回值:
func operation() async -> OperationResult {
// Suspend the current task, and pass its continuation into a closure
// that executes immediately
return await withUnsafeContinuation { continuation in
// Invoke the synchronous callback-based API...
beginOperation(completion: { result in
// ...and resume the continuation when the callback is invoked
continuation.resume(returning: result)
})
}
}
https://github.com/apple/swift-evolution/blob/main/proposals/0300-continuation.md
SE-0304 結(jié)構(gòu)化并發(fā)

async/await proposal 本向并沒有引入并發(fā)性:它只是忽略異步函數(shù)中的掛起點,它將以與同步函數(shù)基本相同的方式執(zhí)行。而這個 proposal 的目標(biāo)就是在 Swift 中引入結(jié)構(gòu)化并發(fā)的支持,并允許高效實現(xiàn)的模型來并發(fā)執(zhí)行異步代碼。
例如以下一段準(zhǔn)備晚餐的代碼:
func chopVegetables() async throws -> [Vegetable] { ... }
func marinateMeat() async -> Meat { ... }
func preheatOven(temperature: Double) async throws -> Oven { ... }
// ...
func makeDinner() async throws -> Meal {
let veggies = try await chopVegetables()
let meat = await marinateMeat()
let oven = try await preheatOven(temperature: 350)
let dish = Dish(ingredients: [veggies, meat])
return try await oven.cook(dish, duration: .hours(3))
}
makeDinner 中的每個步驟都是異步操作,不過整個流程每個點都會暫停,直到當(dāng)前步驟完成。而為了更快地準(zhǔn)備好晚餐,我們需要同時執(zhí)行其中一些步驟,為此,可以將步驟分解為可以并行發(fā)生的不同任務(wù)。而這個 proposal 所提的結(jié)構(gòu)化并發(fā),就可以完成這種任務(wù)。proposal 中的概念很多,在此不詳細介紹。在使用結(jié)構(gòu)化并發(fā)對上述代碼改造后,代碼類似于以下:
func makeDinner() async throws -> Meal {
// Prepare some variables to receive results from our concurrent child tasks
var veggies: [Vegetable]?
var meat: Meat?
var oven: Oven?
enum CookingStep {
case veggies([Vegetable])
case meat(Meat)
case oven(Oven)
}
// Create a task group to scope the lifetime of our three child tasks
try await withThrowingTaskGroup(of: CookingStep.self) { group in
group.async {
try await .veggies(chopVegetables())
}
group.async {
await .meat(marinateMeat())
}
group.async {
try await .oven(preheatOven(temperature: 350))
}
for try await finishedStep in group {
switch finishedStep {
case .veggies(let v): veggies = v
case .meat(let m): meat = m
case .oven(let o): oven = o
}
}
}
// If execution resumes normally after `withTaskGroup`, then we can assume
// that all child tasks added to the group completed successfully. That means
// we can confidently force-unwrap the variables containing the child task
// results here.
let dish = Dish(ingredients: [veggies!, meat!])
return try await oven!.cook(dish, duration: .hours(3))
}
https://github.com/apple/swift-evolution/blob/main/proposals/0304-structured-concurrency.md
SE-0306 Actors

Swift 并發(fā)模型旨在提供一種安全的編程模型,該模型可靜態(tài)檢測數(shù)據(jù)競爭和其他常見的并發(fā)錯誤。結(jié)構(gòu)化并發(fā)提議引入了一種定義并發(fā)任務(wù)的方法,并為函數(shù)和閉包提供了數(shù)據(jù)爭用安全性。該模型適用于許多常見的設(shè)計模式,包括諸如并行映射和并發(fā)回調(diào)模式之類,但僅限于使用由閉包捕獲的狀態(tài)。
Swift 包含一些類,這些類提供了一種聲明可變狀態(tài)的機制,這些狀態(tài)可以在程序之間共享。然而,類很難在并發(fā)程序中正確使用,需要手動同步以避免數(shù)據(jù)競爭。我們希望提供使用共享可變狀態(tài)的功能,同時仍提供對數(shù)據(jù)競爭和其他常見并發(fā)錯誤的靜態(tài)檢測。
actor 模型定義了稱為該角色的實體,非常適合此任務(wù)。Actor 允許聲明并發(fā)域中包含的狀態(tài)包,然后定義對其執(zhí)行操作的多個操作。每個 actor 都通過數(shù)據(jù)隔離來保護自己的數(shù)據(jù),從而確保即使在許多客戶端同時發(fā)出參與者請求的情況下,在給定的時間也只有一個線程可以訪問該數(shù)據(jù)。作為 Swift 并發(fā)模型的一部分,actor 提供了與結(jié)構(gòu)化并發(fā)相同的競爭和內(nèi)存安全屬性。
actor 是一種引用類型,可保護對其可變狀態(tài)的訪問,并隨關(guān)鍵字 actor 一起引入:
actor BankAccount {
let accountNumber: Int
var balance: Double
init(accountNumber: Int, initialDeposit: Double) {
self.accountNumber = accountNumber
self.balance = initialDeposit
}
}
像其他 Swift 類型一樣,actor 可以有初始化器,方法,屬性和下標(biāo)。它們可以擴展并符合協(xié)議,可以是通用的,也可以與通用一起使用。
主要區(qū)別在于 actor 可以保護其狀態(tài)免受數(shù)據(jù)爭奪。這是 Swift 編譯器通過強制使用 actor 及其實例成員的方式受到一系列限制而靜態(tài)地強制實施的,統(tǒng)稱為 actor 隔離。
https://github.com/apple/swift-evolution/blob/main/proposals/0306-actors.md
SE-0307 允許互換使用 CGFloat 和 Double 類型

Swift 首次發(fā)布時,CGFloat 的類型的使用就是一項挑戰(zhàn)。當(dāng)時,大多數(shù) iOS 設(shè)備仍為 32 位。諸如 CoreGraphics 之類的 SDK 提供的 API 在 32 位平臺上采用 32 位浮點值,在 64 位平臺上采用 64 位值。首次引入這些 API 時,在 32 位平臺上 32 位標(biāo)量算術(shù)速度更快,但是到 Swift 發(fā)行時,情況已不再如此:直到今天, 64 位標(biāo)量算術(shù)速度與 32 位一樣快。甚至在 32 位平臺上也是如此。之所以仍然保留了 32/64 位分割,主要是出于源和 ABI 穩(wěn)定性的原因。
而這個 proposal 目標(biāo)是允許 Double 和 CGFloat 類型通過將一種類型透明轉(zhuǎn)換為另一種類型。
https://github.com/apple/swift-evolution/blob/main/proposals/0307-allow-interchangeable-use-of-double-cgfloat-types.md
SE-0308 #if 支持后綴成員表達式

Swift 有條件編譯塊 #if ... #endif,它允許根據(jù)一個或多個編譯條件的值對代碼進行條件編譯。當(dāng)前,與 C 語言中的 #if 不同的是,每個子句的主體必須包含完整的語句。但是,在某些情況下,尤其是在結(jié)果生成器上下文中,出現(xiàn)了將 #if 應(yīng)用于部分表達式的需求。這個該 proposal 擴展了 #if ... #endif以便能夠包圍后綴成員表達式。
例如當(dāng)前使用的如下代碼:
VStack {
let basicView = Text("something")
#if os(iOS)
basicView
.iOSSpecificModifier()
.commonModifier()
#else
basicView
.commonModifier()
#endif
}
可以改成以下這種方式
VStack {
Text("something")
#if os(iOS)
.iOSSpecificModifier()
#endif
.commonModifier()
}
https://github.com/apple/swift-evolution/blob/main/proposals/0308-postfix-if-config-expressions.md
SE-0310 有效的只讀屬性

異步函數(shù)旨在用于可能會或始終會在返回之前暫停執(zhí)行上下文切換的計算,但缺乏有效的只讀計算屬性和下標(biāo),因此這個 proposal 升級了 Swift 的只讀屬性以支持異步并單獨或一起拋出關(guān)鍵字,從而使它們明顯更靈活。
為了說明這一點,我們可以創(chuàng)建一個 BundleFile 結(jié)構(gòu)體,嘗試將其內(nèi)容加載到應(yīng)用程序的資源包中。由于文件可能不存在,或者可能存在但由于某種原因而無法讀取,或者可能可讀但太大,因此需要花費一些時間才能讀取,因此我們可以將 contents 屬性標(biāo)記為異步拋出,如下所示:
enum FileError: Error {
case missing, unreadable
}
struct BundleFile {
let filename: String
var contents: String {
get async throws {
guard let url = Bundle.main.url(forResource: filename, withExtension: nil) else {
throw FileError.missing
}
do {
return try String(contentsOf: url)
} catch {
throw FileError.unreadable
}
}
}
}
因為 content 既是異步的又是拋出的,所以我們在嘗試讀取它時必須使用 try await:
func printHighScores() async throws {
let file = BundleFile(filename: "highscores")
try await print(file.contents)
}
https://github.com/apple/swift-evolution/blob/main/proposals/0310-effectful-readonly-properties.md
SE-0316 全局 actors

Actor 非常適合隔離實例數(shù)據(jù),但是當(dāng)需要隔離的數(shù)據(jù)分散在整個程序中,或者表示程序外部存在的某種狀態(tài)時,將所有代碼和數(shù)據(jù)都放入單個actor 實例中可能是不切實際的(例如,大型程序)甚至是不可能的(與那些假設(shè)無處不在的系統(tǒng)進行交互時)。
global actors 的主要目標(biāo)是將 actor 模型應(yīng)用于只能由主線程訪問的狀態(tài)和操作。在應(yīng)用程序中,主線程通常負(fù)責(zé)執(zhí)行主要的事件處理循環(huán),該循環(huán)處理來自各種來源的事件并將其傳遞給應(yīng)用程序代碼。global actors 提供了一種機制,可以利用 actor 的角色來描述主線程,利用 Swift 的 actor 隔離模型來幫助正確使用主線程。
@MainActor var globalTextSize: Int
@MainActor func increaseTextSize() {
globalTextSize += 2 // okay:
}
func notOnTheMainActor() async {
globalTextSize = 12 // error: globalTextSize is isolated to MainActor
increaseTextSize() // error: increaseTextSize is isolated to MainActor, cannot call synchronously
await increaseTextSize() // okay: asynchronous call hops over to the main thread and executes there
}
https://github.com/apple/swift-evolution/blob/main/proposals/0316-global-actors.md
SE-0317 async let bindings

結(jié)構(gòu)化并發(fā)提供了一個范式,用于在有范圍的任務(wù)組中生成并發(fā)子任務(wù),建立定義明確的任務(wù)層次結(jié)構(gòu),從而可以透明地處理并發(fā)管理的取消,錯誤傳播,優(yōu)先級管理和其他棘手的細節(jié)。
這個 proposal 旨在使用類似于 let 綁定的輕量級語法,使生成子任務(wù)的常規(guī)任務(wù)異步運行,并將最終結(jié)果傳遞給父任務(wù)。
還是以午餐為例,使用 async let,那么代碼看起來是下面這種:
func makeDinner() async throws -> Meal {
async let veggies = chopVegetables()
async let meat = marinateMeat()
async let oven = preheatOven(temperature: 350)
let dish = Dish(ingredients: await [try veggies, meat])
return try await oven.cook(dish, duration: .hours(3))
}
https://github.com/apple/swift-evolution/blob/main/proposals/0317-async-let.md
小結(jié)
這里只是整理了部分在 Swift 5.5 中實現(xiàn)的 proposal 或者是在當(dāng)前 main 快照中審核的 proposal。可以看到 async/await 及一些異步模型將會是 Swift 5.5 的重點內(nèi)容。當(dāng)然,最終 Swift 5.5 會新增哪些特性,還需要等最后的結(jié)果。也許 Swift 團隊會將一些新特性放到 Swift 6 中發(fā)布。讓我們期待一下 WWDC21 吧。
-End-
最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

面試題】即可獲取
