如何在Swift 5.5中使用SwiftUI的async/await?

bkkx9g8r  于 2023-02-21  发布在  Swift
关注(0)|答案(5)|浏览(343)

我一直在测试Swift 5.5版本中预览的async/await功能,但我无法收集async函数的结果并使用SwiftUI显示它们。

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"调用
将"async"添加到函数"fetchText()"以使其异步
然后,将async添加到fetchText()函数会导致.onAppear()函数出现以下错误:
从类型为"()async-〉()"的"async"函数到同步函数类型"()-〉Void"的转换无效
this article中,它们使用@asyncHandler标记来注解fetchText函数,但这会导致警告:'@asyncHandler' has been removed from the language'.

mkshixfv

mkshixfv1#

我是你提到的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

q5lcpyga

q5lcpyga2#

根据WWDC会话Meet async/await in Swift WWDC21中的新信息,在23 m:28 s,现在使用以下方法完成:

Task {
   someState = await someAsyncFunction()
}

会议截图。

注意有很多方法可以示例化一个任务。这是最基本的。你也可以使用Task.detached,两种方法都可以得到一个priority参数。同时检查Task docs和会话在大约23:05检查Explore structured concurrency in Swift WWDC21(我推荐整个会话!)以获得更多信息。

nr7wwzry

nr7wwzry3#

我同意@peter-friese的回答,但我想为读者补充一下从同步到异步桥接时语法的变化:
新语法:

Task {
   someState = await someAsyncFunction()
}

替换以下语法:

async {
   someState = await someAsyncFunction()
}

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

Task(priority: .userInitiated) {
   someState = await someAsyncFunction()
}
oknrviil

oknrviil4#

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

mec1mxoz5#

从SwiftUI视图调用此简化的.task { }版本

var body: some View {
     VStack(spacing:.default) {
          yourCustomView
        }
        .padding()
      }
      .task { await viewModel.onAppear() }
    }

在视图模型中

func onAppear() async {
    await getStuffFromNetwork()
 }

相关问题