如何在 Swift 5.5 中将 async/await 与 SwiftUI 一起使用?
How can I use async/await with SwiftUI in Swift 5.5?
我一直在测试 Swift 5.5 版本中预览的 async/await 功能,但我无法从异步函数收集结果并使用 Swift[= 显示它们33=]。这是我的代码:
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)
}
}
这会导致以下错误:
'async' call in a function that does not support concurrency
Add 'async' to function 'fetchText()' to make it asynchronous
将 async
添加到 fetchText()
函数然后会导致 .onAppear()
函数出现以下错误:
Invalid conversion from 'async' function of type '() async -> ()' to synchronous function type '() -> Void'
在 this article 中,他们使用 @asyncHandler
标记来注释 fetchText
函数,但这会导致警告:'@asyncHandler' has been removed from the language'
.
我是您引用的 the article 的作者。
如 Discover concurrency in SwiftUI 中所述,视图可以使用新的 .task { }
和 .refreshable { }
修饰符来异步获取数据。
因此,您现在可以通过以下选项调用异步代码:
func someSyncMethod() {
doSomeSyncWork()
Task {
await methodThatIsAsync()
}
}
List {
}
.task {
await methodThatIsAsync()
}
List {
}
.refreshable {
await methodThatIsAsync()
}
如果您使用的是单独的视图模型,请确保将其标记为 @MainActor
以确保 属性 更新在主要角色上执行。
我更新了文章的代码:https://github.com/peterfriese/Swift-Async-Await-Experiments
根据 WWDC 中的新信息 session 在 Swift 中与 async/await 会面
WWDC,在 23m:28s 现在使用:
async {
someState = await someAsyncFunction()
}
来自 session 的屏幕截图。
我同意@peter-friese 的回答,但会为那些阅读这篇文章的人添加从同步桥接到异步时语法的变化:
新语法:
Task {
someState = await someAsyncFunction()
}
替换此语法:
async {
someState = await someAsyncFunction()
}
... 并且 Task()
初始化程序可以接受优先级参数:
Task(priority: .userInitiated) {
someState = await someAsyncFunction()
}
import SwiftUI
struct AsyncTestView: View {
@State var text = "Loading"
// Async function
func asyncGetText() async -> String {
try? await Task.sleep(nanoseconds: 3 * NSEC_PER_SEC)
return "My text"
}
var body: some View {
Text(text)
.task {
text = await asyncGetText()
}
}
}
我一直在测试 Swift 5.5 版本中预览的 async/await 功能,但我无法从异步函数收集结果并使用 Swift[= 显示它们33=]。这是我的代码:
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)
}
}
这会导致以下错误:
'async' call in a function that does not support concurrency
Add 'async' to function 'fetchText()' to make it asynchronous
将 async
添加到 fetchText()
函数然后会导致 .onAppear()
函数出现以下错误:
Invalid conversion from 'async' function of type '() async -> ()' to synchronous function type '() -> Void'
在 this article 中,他们使用 @asyncHandler
标记来注释 fetchText
函数,但这会导致警告:'@asyncHandler' has been removed from the language'
.
我是您引用的 the article 的作者。
如 Discover concurrency in SwiftUI 中所述,视图可以使用新的 .task { }
和 .refreshable { }
修饰符来异步获取数据。
因此,您现在可以通过以下选项调用异步代码:
func someSyncMethod() {
doSomeSyncWork()
Task {
await methodThatIsAsync()
}
}
List {
}
.task {
await methodThatIsAsync()
}
List {
}
.refreshable {
await methodThatIsAsync()
}
如果您使用的是单独的视图模型,请确保将其标记为 @MainActor
以确保 属性 更新在主要角色上执行。
我更新了文章的代码:https://github.com/peterfriese/Swift-Async-Await-Experiments
根据 WWDC 中的新信息 session 在 Swift 中与 async/await 会面 WWDC,在 23m:28s 现在使用:
async {
someState = await someAsyncFunction()
}
来自 session 的屏幕截图。
我同意@peter-friese 的回答,但会为那些阅读这篇文章的人添加从同步桥接到异步时语法的变化:
新语法:
Task {
someState = await someAsyncFunction()
}
替换此语法:
async {
someState = await someAsyncFunction()
}
... 并且 Task()
初始化程序可以接受优先级参数:
Task(priority: .userInitiated) {
someState = await someAsyncFunction()
}
import SwiftUI
struct AsyncTestView: View {
@State var text = "Loading"
// Async function
func asyncGetText() async -> String {
try? await Task.sleep(nanoseconds: 3 * NSEC_PER_SEC)
return "My text"
}
var body: some View {
Text(text)
.task {
text = await asyncGetText()
}
}
}