1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Swift 5.5 新特性搶先看,async/await 將重磅來襲

        共 15909字,需瀏覽 32分鐘

         ·

        2021-06-01 13:41

        再過一周的時(shí)間,WWDC21 就正式舉行了,如果不出意外的話,Swift 5.5 測(cè)試版也會(huì)在期間發(fā)布。早在 3 月 13 日,官方論壇就公布了 Swift 5.5 版本的發(fā)布計(jì)劃,并在 4 月 16 日拉出了 release/5.5 分支。經(jīng)過幾個(gè)月時(shí)間的準(zhǔn)備,從 Swift Evolution 中,我們能發(fā)現(xiàn) Swift 5.5 將為我們帶來許多期待已久的特性,如 async/await。我們今天就來簡單整理一下這些 可能 將在 Swift 5.5 中出現(xiàn)的新特性。

        SE-0291 包集合

        這個(gè) proposal 旨在為 SwiftPM 添加對(duì)包集合的支持。包集合是包和相關(guān)元數(shù)據(jù)的列表,可以更輕松地發(fā)現(xiàn)特定用例的現(xiàn)有包。SwiftPM 將允許用戶訂閱這些集合,通過 swift package-collection 命令行界面搜索它們,并使 libSwiftPM 的任何客戶端都可以訪問它們的內(nèi)容。這個(gè) 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 將屬性包裝器擴(kuò)展到函數(shù)和閉包參數(shù)

        Property Wrappers 用于抽象出常見的屬性訪問器模式,在 Swift 5.1 中引入。不過之前僅允許在局部變量和類型屬性上應(yīng)用屬性包裝器。而這個(gè) proposal 的目標(biāo)是將屬性包裝器擴(kuò)展到函數(shù)和閉包參數(shù)。

        例如,使用來自 PropertyKit 的驗(yàn)證,我們可以將各種前提條件抽象到一個(gè)屬性包裝器中:

        @propertyWrapper
        struct Asserted<Value> {
        init(
        wrappedValue: Value,
        validation: Validation<Value>,
        ) { ... }

        var wrappedValue: Value { ... }
        }

        將 @Asserted 應(yīng)用于參數(shù)以對(duì)參數(shù)值斷言某些先決條件會(huì)很有用。例如,下面的代碼斷言傳遞給 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é)議的值。

        這個(gè) proposal 將擴(kuò)展對(duì)枚舉關(guān)聯(lián)值的一致性的自動(dòng)合成的支持。

        如以下枚舉有關(guān)聯(lián)值:

        enum Command: Codable {
        case load(key: String)
        case store(key: String, value: Int)
        }

        將會(huì)被編碼為

        {
        "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)使用許多異步操作、錯(cuò)誤處理或異步調(diào)用之間的控制流變得復(fù)雜時(shí),會(huì)讓問題變得很復(fù)雜。我們先看一個(gè)簡單的例子:

        // 一系列簡單的異步操作通常需要深度嵌套的閉包
        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)
        }

        而這個(gè)提案則引入了一種語言擴(kuò)展,大大簡化了這些操作,讓代碼更加自然而不易出錯(cuò)。這種設(shè)計(jì)為 Swift 引入了一個(gè)協(xié)程模型。函數(shù)可以是 async,允許程序員使用正常的控制流機(jī)制編寫涉及異步操作的復(fù)雜邏輯。編譯器負(fù)責(zé)將異步函數(shù)轉(zhuǎn)換為一組合適的閉包和狀態(tài)機(jī)。實(shí)際上 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
        }

        不過,這個(gè) proposal 并不提供并發(fā),結(jié)構(gòu)化并發(fā)問題由另一個(gè) 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 平臺(tái)上,Swift 與 Objective-C 的混編與交互目前來講還是一個(gè)很大的課題。在 Objective-C 中,異步 API 隨處可見,在 iOS 14.0 SDK 中就包含了近 1000 個(gè)接受 completion 處理器的方法。例如以下 PassKit API 中的方法

        - (void)signData:(NSData *)signData 
        withSecureElementPass:(PKSecureElementPass *)secureElementPass
        completion:(void (^)(NSData *signedData, NSData *signature, NSError *error))completion;

        這些方法包括可以直接在 Swift 中調(diào)用的方法,可以在 Swift 定義的子類中覆蓋的方法,以及可以實(shí)現(xiàn)的協(xié)議中的方法。

        當(dāng)前,以上 Objective-C 函數(shù)在 Swift 中會(huì)被翻譯成以下函數(shù):

        @objc func sign(_ signData: Data, 
        using secureElementPass: PKSecureElementPass,
        completion: @escaping (Data?, Data?, Error?) -> Void
        )

        這個(gè) proposal 旨在為 Swift 并發(fā)結(jié)構(gòu)與 Objective-C 之間提供互操作性,并實(shí)現(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ù)將會(huì)被翻譯為以下 async 函數(shù):

        @objc func sign(
        _ signData: Data,
        using secureElementPass: PKSecureElementPass
        )
        async throws -> (Data, Data)

        同時(shí)可以通過以下方式來調(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 提供了更直觀的異步編程方式。而這個(gè) proposal 的目標(biāo)是基于 async/await,以內(nèi)置的方式更直觀地編寫和使用隨時(shí)間返回多個(gè)值的函數(shù)。

        這個(gè) proposal 主要由三個(gè)部分組成:

        • 表示異步值序列的協(xié)議的標(biāo)準(zhǔn)庫定義;

        • 編譯器支持在異步值序列上使用 for...in 語法;

        • 對(duì)異步值序列進(jìn)行操作的常用函數(shù)的標(biāo)準(zhǔn)庫實(shí)現(xiàn)

        基于這個(gè) proposal,迭代異步值序列像迭代同步值序列一樣簡單。一個(gè)示例用例是迭代文件中的行,如下所示:

        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)庫還將擴(kuò)展協(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 在通用上下文中擴(kuò)展靜態(tài)成員查找

        Swift 支持對(duì)具體類型的靜態(tài)成員查找,并通過類似枚舉的 . 語法來調(diào)用。例如,SwiftUI 中使用預(yù)定義的常用值作為靜態(tài)屬性擴(kuò)展了 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)成員查找目前存在一個(gè)問題:不支持泛型函數(shù)中的協(xié)議成員,所以沒有辦法使用 . 語法來調(diào)用,如 SwiftUI 定義了一個(gè) 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 修飾符時(shí)將具體類型以全名方式寫入 ToggleStyle:

        Toggle("Wi-Fi", isOn: $isWiFiEnabled)
        .toggleStyle(SwitchToggleStyle())

        而這個(gè) proposal 的目標(biāo)是放寬對(duì)協(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ù),這會(huì)掛起任務(wù),并產(chǎn)生一個(gè)值,同步代碼隨后可以通過該值使用句柄來恢復(fù)任務(wù)。例如

        func beginOperation(completion: (OperationResult) -> Void)

        我們可以通過掛起任務(wù)并在調(diào)用回調(diào)時(shí)使用其連續(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ù)中的掛起點(diǎn),它將以與同步函數(shù)基本相同的方式執(zhí)行。而這個(gè) proposal 的目標(biāo)就是在 Swift 中引入結(jié)構(gòu)化并發(fā)的支持,并允許高效實(shí)現(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 中的每個(gè)步驟都是異步操作,不過整個(gè)流程每個(gè)點(diǎn)都會(huì)暫停,直到當(dāng)前步驟完成。而為了更快地準(zhǔn)備好晚餐,我們需要同時(shí)執(zhí)行其中一些步驟,為此,可以將步驟分解為可以并行發(fā)生的不同任務(wù)。而這個(gè) proposal 所提的結(jié)構(gòu)化并發(fā),就可以完成這種任務(wù)。proposal 中的概念很多,在此不詳細(xì)介紹。在使用結(jié)構(gòu)化并發(fā)對(duì)上述代碼改造后,代碼類似于以下:

        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)檢測(cè)數(shù)據(jù)競爭和其他常見的并發(fā)錯(cuò)誤。結(jié)構(gòu)化并發(fā)提議引入了一種定義并發(fā)任務(wù)的方法,并為函數(shù)和閉包提供了數(shù)據(jù)爭用安全性。該模型適用于許多常見的設(shè)計(jì)模式,包括諸如并行映射和并發(fā)回調(diào)模式之類,但僅限于使用由閉包捕獲的狀態(tài)。

        Swift 包含一些類,這些類提供了一種聲明可變狀態(tài)的機(jī)制,這些狀態(tài)可以在程序之間共享。然而,類很難在并發(fā)程序中正確使用,需要手動(dòng)同步以避免數(shù)據(jù)競爭。我們希望提供使用共享可變狀態(tài)的功能,同時(shí)仍提供對(duì)數(shù)據(jù)競爭和其他常見并發(fā)錯(cuò)誤的靜態(tài)檢測(cè)。

        actor 模型定義了稱為該角色的實(shí)體,非常適合此任務(wù)。Actor 允許聲明并發(fā)域中包含的狀態(tài)包,然后定義對(duì)其執(zhí)行操作的多個(gè)操作。每個(gè) actor 都通過數(shù)據(jù)隔離來保護(hù)自己的數(shù)據(jù),從而確保即使在許多客戶端同時(shí)發(fā)出參與者請(qǐng)求的情況下,在給定的時(shí)間也只有一個(gè)線程可以訪問該數(shù)據(jù)。作為 Swift 并發(fā)模型的一部分,actor 提供了與結(jié)構(gòu)化并發(fā)相同的競爭和內(nèi)存安全屬性。

        actor 是一種引用類型,可保護(hù)對(duì)其可變狀態(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)。它們可以擴(kuò)展并符合協(xié)議,可以是通用的,也可以與通用一起使用。

        主要區(qū)別在于 actor 可以保護(hù)其狀態(tài)免受數(shù)據(jù)爭奪。這是 Swift 編譯器通過強(qiáng)制使用 actor 及其實(shí)例成員的方式受到一系列限制而靜態(tài)地強(qiáng)制實(shí)施的,統(tǒng)稱為 actor 隔離。

        https://github.com/apple/swift-evolution/blob/main/proposals/0306-actors.md

        SE-0307 允許互換使用 CGFloat 和 Double 類型

        Swift 首次發(fā)布時(shí),CGFloat 的類型的使用就是一項(xiàng)挑戰(zhàn)。當(dāng)時(shí),大多數(shù) iOS 設(shè)備仍為 32 位。諸如 CoreGraphics 之類的 SDK 提供的 API 在 32 位平臺(tái)上采用 32 位浮點(diǎn)值,在 64 位平臺(tái)上采用 64 位值。首次引入這些 API 時(shí),在 32 位平臺(tái)上 32 位標(biāo)量算術(shù)速度更快,但是到 Swift 發(fā)行時(shí),情況已不再如此:直到今天, 64 位標(biāo)量算術(shù)速度與 32 位一樣快。甚至在 32 位平臺(tái)上也是如此。之所以仍然保留了 32/64 位分割,主要是出于源和 ABI 穩(wěn)定性的原因。

        而這個(gè) 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 支持后綴成員表達(dá)式

        Swift 有條件編譯塊 #if ... #endif,它允許根據(jù)一個(gè)或多個(gè)編譯條件的值對(duì)代碼進(jìn)行條件編譯。當(dāng)前,與 C 語言中的 #if 不同的是,每個(gè)子句的主體必須包含完整的語句。但是,在某些情況下,尤其是在結(jié)果生成器上下文中,出現(xiàn)了將 #if 應(yīng)用于部分表達(dá)式的需求。這個(gè)該 proposal 擴(kuò)展了 #if ... #endif以便能夠包圍后綴成員表達(dá)式。

        例如當(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ù)旨在用于可能會(huì)或始終會(huì)在返回之前暫停執(zhí)行上下文切換的計(jì)算,但缺乏有效的只讀計(jì)算屬性和下標(biāo),因此這個(gè) proposal 升級(jí)了 Swift 的只讀屬性以支持異步并單獨(dú)或一起拋出關(guān)鍵字,從而使它們明顯更靈活。

        為了說明這一點(diǎn),我們可以創(chuàng)建一個(gè) BundleFile 結(jié)構(gòu)體,嘗試將其內(nèi)容加載到應(yīng)用程序的資源包中。由于文件可能不存在,或者可能存在但由于某種原因而無法讀取,或者可能可讀但太大,因此需要花費(fèi)一些時(shí)間才能讀取,因此我們可以將 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
        }
        }
        }
        }

        因?yàn)?content 既是異步的又是拋出的,所以我們?cè)趪L試讀取它時(shí)必須使用 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í)例數(shù)據(jù),但是當(dāng)需要隔離的數(shù)據(jù)分散在整個(gè)程序中,或者表示程序外部存在的某種狀態(tài)時(shí),將所有代碼和數(shù)據(jù)都放入單個(gè)actor 實(shí)例中可能是不切實(shí)際的(例如,大型程序)甚至是不可能的(與那些假設(shè)無處不在的系統(tǒng)進(jìn)行交互時(shí))。

        global actors 的主要目標(biāo)是將 actor 模型應(yīng)用于只能由主線程訪問的狀態(tài)和操作。在應(yīng)用程序中,主線程通常負(fù)責(zé)執(zhí)行主要的事件處理循環(huán),該循環(huán)處理來自各種來源的事件并將其傳遞給應(yīng)用程序代碼。global actors 提供了一種機(jī)制,可以利用 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ā)提供了一個(gè)范式,用于在有范圍的任務(wù)組中生成并發(fā)子任務(wù),建立定義明確的任務(wù)層次結(jié)構(gòu),從而可以透明地處理并發(fā)管理的取消,錯(cuò)誤傳播,優(yōu)先級(jí)管理和其他棘手的細(xì)節(jié)。

        這個(gè) proposal 旨在使用類似于 let 綁定的輕量級(jí)語法,使生成子任務(wù)的常規(guī)任務(wù)異步運(yùn)行,并將最終結(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 中實(shí)現(xiàn)的 proposal 或者是在當(dāng)前 main 快照中審核的 proposal??梢钥吹?async/await 及一些異步模型將會(huì)是 Swift 5.5 的重點(diǎn)內(nèi)容。當(dāng)然,最終 Swift 5.5 會(huì)新增哪些特性,還需要等最后的結(jié)果。也許 Swift 團(tuán)隊(duì)會(huì)將一些新特性放到 Swift 6 中發(fā)布。讓我們期待一下 WWDC21 吧。



        推薦閱讀

        ?  為 iPad 部署基于 VS Code 的遠(yuǎn)程開發(fā)環(huán)境
        ?  “And away we code. ” WWDC21 超 200 個(gè) Session 等著你
        ?  Google 正式發(fā)布 Fuchsia OS,F(xiàn)lutter 集成尚存問題
        ?  京東APP訂單業(yè)務(wù)Swift優(yōu)化總結(jié)


        就差您點(diǎn)一下了 ??????

        瀏覽 77
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            日本老熟妇 | xxxx少妇捆绑绳艺捆绑 | 台湾一级黄色大片 | 男生的鸡鸡插入女生的鸡鸡 | 大香蕉国产 | 白嫩在线观看 | 国产精品久久777777 | 西西人体大胆瓣开腿自慰 | 精品9l九九九九九77777 | 久久艹视频|