简体   繁体   English

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

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

I have been testing the async/await functionality previewed in the Swift 5.5 release, but I am unable to collect the results from an async function and display them using SwiftUI.我一直在测试 Swift 5.5 版本中预览的异步/等待功能,但我无法从异步 function 收集结果并使用 Z5D807DF8E2D0F6FCC3B5037B78AB9D09. Here is my code:这是我的代码:

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)
    }
}

This results in the following error:这会导致以下错误:

'async' call in a function that does not support concurrency不支持并发的 function 中的“异步”调用
Add 'async' to function 'fetchText()' to make it asynchronous将 'async' 添加到 function 'fetchText()' 以使其异步

Adding async to the fetchText() function then results in the following error on the .onAppear() function:async添加到fetchText() function 然后在 .onAppear .onAppear() ) function 上导致以下错误:

Invalid conversion from 'async' function of type '() async -> ()' to synchronous function type '() -> Void'从 '() async -> ()' 类型的 'async' function 到同步 function 类型 '() -> Void' 的无效转换

In this article , they use the @asyncHandler tag to annotate the fetchText function, however this results in the warning: '@asyncHandler' has been removed from the language' .本文中,他们使用@asyncHandler标签来注释fetchText function,但是这会导致警告: '@asyncHandler' has been removed from the language'

I'm the author of the article you referenced.我是你引用的文章的作者。

As discussed in Discover concurrency in SwiftUI , views can make use of the new .task { } and .refreshable { } modifiers to fetch data asynchronously.正如在 SwiftUI 中发现并发中所讨论的,视图可以使用新的.task { }.refreshable { }修饰符来异步获取数据。

So you now have the following options to call you async code:所以你现在有以下选项来调用你的异步代码:

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

If you're using a separate view model, make sure to mark it as @MainActor to ensure property updates get executed on the main actor.如果您使用单独的视图 model,请确保将其标记为@MainActor以确保在主要参与者上执行属性更新。

I updated the code for my article: https://github.com/peterfriese/Swift-Async-Await-Experiments我更新了我的文章的代码: https://github.com/peterfriese/Swift-Async-Await-Experiments

As per new informations in WWDC session Meet async/await in Swift WWDC , at 23m:28s this is now done using:根据 WWDC session 中的新信息,在 Swift WWDC 中遇到 async/await ,在 23m:28s 时,现在使用:

async {
   await someAsyncFunction()
}

Screenshot from the session. session 的屏幕截图。

在此处输入图像描述

I agree with @peter-friese's answer but will add for those reading this the change of syntax when bridging from sync to async:我同意@peter-friese 的回答,但会为那些阅读本文的人添加从同步到异步桥接时语法的变化:

The new syntax:新语法:

Task {
   await someAsyncFunction()
}

Replaces this syntax:替换此语法:

async {
   await someAsyncFunction()
}

... and the Task() initialiser can accept a priority parameter: ...并且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