这是苹果开发者文档\xe3\x80\x82中的代码
\nlet url = URL(string: "https://example.com")!\n@State private var message = "Loading..."\n\nvar body: some View {\n Text(message)\n .task {\n do {\n var receivedLines = [String]()\n for try await line in url.lines {\n receivedLines.append(line)\n message = "Received \\(receivedLines.count) lines"\n }\n } catch {\n message = "Failed to load"\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n为什么不在messageUI 线程中更新,如下代码所示
DispatchQueue.main.async {\n message = "Received \\(receivedLines.count) lines"\n}\nRun Code Online (Sandbox Code Playgroud)\n任务块中的代码是否始终在UI线程中运行?
\n这是我的测试代码。有时任务似乎没有继承其调用者的参与者上下文。
\nfunc wait() async {\n await Task.sleep(1000000000)\n}\n\nThread.current.name = "Main thread"\nprint("Thread in top-level is \\(Thread.current.name)")\n\nTask {\n print("Thread in task before wait is \\(Thread.current.name)")\n if Thread.current.name!.isEmpty {\n Thread.current.name = "Task thread"\n print("Change thread name \\(Thread.current.name)")\n }\n await wait()\n print("Thread in task after wait is \\(Thread.current.name)")\n\n}\n\nThread.sleep(until: .now + 2)\n\n// print as follow\n\n// Thread in top-level is Optional("Main thread")\n// Thread in task before wait is Optional("")\n// Change thread name Optional("Task thread")\n// Thread in task after wait is Optional("")\nRun Code Online (Sandbox Code Playgroud)\n任务中的线程前后不同wait()
任务中的线程不是Main thread
好问题!看起来像是一个bug,但实际上Apple的示例代码是安全的。但出于某种偷偷摸摸的原因,它是一个保险箱。
打开终端窗口并运行以下命令:
cd /Applications/Xcode.app
find . -path */iPhoneOS.platform/*/SwiftUI.swiftmodule/arm64.swiftinterface
Run Code Online (Sandbox Code Playgroud)
该find命令可能需要一段时间才能完成,但它最终会打印如下路径:
./Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/System/Library/Frameworks/SwiftUI.framework/Modules/SwiftUI.swiftmodule/arm64.swiftinterface
Run Code Online (Sandbox Code Playgroud)
使用 查看该swiftinterface文件并less搜索func task. 您将找到修饰符的真正task定义。我将在这里复制它并换行以使其更易于阅读:
@inlinable
public func task(
priority: _Concurrency.TaskPriority = .userInitiated,
@_inheritActorContext
_ action: @escaping @Sendable () async -> Swift.Void
) -> some SwiftUI.View {
modifier(_TaskModifier(priority: priority, action: action))
}
Run Code Online (Sandbox Code Playgroud)
请注意,action参数具有@_inheritActorContext属性。这是一个私有属性,但Underscored Attributes ReferenceSwift 存储库中的 解释了它的作用:
标记
@Sendable async闭包参数应该基于闭包的声明站点继承参与者上下文(即它应该在哪个参与者上运行)。这与典型的行为不同,在典型的行为中,闭包可以在任何地方运行,除非其类型明确声明它将在特定的参与者上运行。
因此task修饰符的action闭包继承了围绕修饰符使用的参与者上下文task。示例代码task在bodya 的属性内使用修饰符View。body您还可以在该文件中找到属性的真实声明swiftinterface:
@SwiftUI.ViewBuilder @_Concurrency.MainActor(unsafe) var body: Self.Body { get }
Run Code Online (Sandbox Code Playgroud)
该body方法具有MainActor属性,这意味着它属于上下文MainActor。MainActor在主线程/队列上运行。因此,使用taskinsidebody意味着task闭包也在主线程/队列上运行。
| 归档时间: |
|
| 查看次数: |
1153 次 |
| 最近记录: |