此处需要显式使用 MainActor.run

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

文档中不清楚该做什么。我的理解是:

  1. Task 继承了它的 actor 上下文,因此从这里的主体内部,它将成为主要 actor。
  2. 任何异步函数都可能进入协作线程池,因此它可能会脱离主线程运行。

我不确定的是

data
的设定是否会隐含在主角身上。

struct ExampleView: View {
    @State private var data = "Initial data"

    var body: some View {
        Text(data)
            .onAppear {
                Task {
                    let fetchedData = await fetchData()
                    await MainActor.run {
                        data = fetchedData // Explicitly updating on the main thread
                    }
                }
            }
    }

    func fetchData() async -> String {
        // Simulate a network request or heavy computation
        await Task.sleep(1_000_000_000) // 1 second delay
        return "Updated data"
    }
}
swiftui concurrency actor
1个回答
0
投票

Task 继承了它的 actor 上下文,因此从这里的主体内部,它将成为主要 actor。

正确,所以即使没有

data
,也会将
MainActor.run
设置在主角身上。展示这一点的一个简单方法是将
data
标记为
@MainActor
,将其与主要演员隔离。您仍然可以在
data
中设置
Task
,无需等待。

任何异步函数都可能进入协作线程池,因此它可能会脱离主线程运行。

如果异步函数没有与主要参与者隔离,那么是的。但所有其他不与主要参与者隔离的代码也是如此。您始终可以使用

Task.detached { ... }
在协作线程池中的某个线程上运行代码,或者在不与主要参与者隔离的上下文中使用
Task { ... }

// suppose this is a global function, therefore not isolated to anything
func foo() {
    Task {
        // code here will run in the co-operative thread pool
    }
}

因为一旦你触及暂停点,它可能会改变其后所有内容的上下文。

不。如果任务与主要参与者隔离,则它将始终在主线程上运行。如果它与其他某个参与者隔离,它将始终在该参与者上运行(尽管它运行的线程可能会发生变化,因为参与者和线程没有一对一的关系)。

旁注:您可以写

.task { ... }
而不是
.onAppear { Task { ... } }

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