任务修改器有什么作用?

问题描述 投票:0回答:1

例如:

var body: some View {
    ScrollViewReader(content: { proxy in
        /* ... */
    }).task {
        do {
            let url = URL(string: "https://example.com/data.json")!
            let (data, _) = try await URLSession.shared.data(from: url)
            /* ... */
        } catch {
            print(error)
        }
    }
}

.task
修饰符在下面有什么作用?是用于在数据请求解决后存储和恢复程序的状态吗?

swift swiftui concurrency
1个回答
1
投票

Swift 并发世界的关键。

SwiftUI 的

.task
修饰符从周围的函数继承其 actor 上下文。如果您在视图的 body 属性内调用
.task
,异步操作将在主要参与者上运行,因为
View.body
(半秘密地)用
@MainActor
进行注释。但是,如果您从未添加
.task
注释的辅助属性或函数调用
@MainActor
,则异步操作将在协作线程池中运行。

根据苹果文档:

使用此修饰符可以执行异步任务,其生命周期与修改后的视图的生命周期相匹配。如果在 SwiftUI 删除视图或视图更改标识之前任务未完成,SwiftUI 将取消该任务。

在任务中使用

await
关键字来等待异步调用完成,或等待
AsyncSequence
实例的值。例如,您可以修改文本视图以启动从远程资源加载内容的任务:

let url = URL(string: "https://example.com")!
@State private var message = "Loading..."


var body: some View {
    Text(message)
        .task {
            do {
                var receivedLines = [String]()
                for try await line in url.lines {
                    receivedLines.append(line)
                    message = "Received \(receivedLines.count) lines"
                }
            } catch {
                message = "Failed to load"
            }
        }
}

此示例使用

lines
方法以异步字符串序列的形式获取存储在指定 URL 的内容。当每个新行到达时,for-await-in 循环的主体将该行存储在字符串数组中,并更新文本视图的内容以报告最新的行数。

© www.soinside.com 2019 - 2024. All rights reserved.