繁体   English   中英

如何在 Swift 5.5 中将 async/await 与 SwiftUI 一起使用?

[英]How can I use async/await with SwiftUI in Swift 5.5?

我一直在测试 Swift 5.5 版本中预览的异步/等待功能,但我无法从异步 function 收集结果并使用 Z5D807DF8E2D0F6FCC3B5037B78AB9D09. 这是我的代码:

import SwiftUI

struct AsyncTestView: View {
    @State var text: String?

    // Async function
    func asyncGetText() async -> String {
        Thread.sleep(forTimeInterval: 10)
        return "My text"
    }
    
    // Stores the result of async function
    func fetchText() async {
        let text = await asyncGetText()
        DispatchQueue.main.async {
            self.text = text
        }
    }
    
    var body: some View {
        Text(text ?? "Loading")
            .onAppear(perform: fetchText)
    }
}

这会导致以下错误:

不支持并发的 function 中的“异步”调用
将 'async' 添加到 function 'fetchText()' 以使其异步

async添加到fetchText() function 然后在 .onAppear .onAppear() ) function 上导致以下错误:

从 '() async -> ()' 类型的 'async' function 到同步 function 类型 '() -> Void' 的无效转换

本文中,他们使用@asyncHandler标签来注释fetchText function,但是这会导致警告: '@asyncHandler' has been removed from the language'

我是你引用的文章的作者。

正如在 SwiftUI 中发现并发中所讨论的,视图可以使用新的.task { }.refreshable { }修饰符来异步获取数据。

所以你现在有以下选项来调用你的异步代码:

func someSyncMethod() {
  doSomeSyncWork()
  async {
    await methodThatIsAsync()
  }
}
List {
}
.task {
  await methodThatIsAsync()
}
List {
}
.refreshable {
  await methodThatIsAsync()
}

如果您使用单独的视图 model,请确保将其标记为@MainActor以确保在主要参与者上执行属性更新。

我更新了我的文章的代码: https://github.com/peterfriese/Swift-Async-Await-Experiments

根据 WWDC session 中的新信息,在 Swift WWDC 中遇到 async/await ,在 23m:28s 时,现在使用:

async {
   await someAsyncFunction()
}

session 的屏幕截图。

在此处输入图像描述

我同意@peter-friese 的回答,但会为那些阅读本文的人添加从同步到异步桥接时语法的变化:

新语法:

Task {
   await someAsyncFunction()
}

替换此语法:

async {
   await someAsyncFunction()
}

...并且Task()初始化程序可以接受优先级参数:

Task(priority: .userInitiated) {
   await someAsyncFunction()
}
import SwiftUI

struct AsyncTestView: View {
    @State var text = “Loading”

    // Async function
    func asyncGetText() async -> String {
        Thread.sleep(forTimeInterval: 10) // Maybe should be Task.sleep
        return "My text"
    }
    
    var body: some View {
        Text(text)
        .task {
             text = await asyncGetText()
        }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM