SwiftUI 视图与 @MainActor

SwiftUI 视图与 @MainActor

💡 原文中文,约7400字,阅读约需18分钟。
📝

内容提要

越来越多的开发者开始尝试开启并发严格检查选项,为 Swift 6 的到来做准备。在收到的警告和错误中,有一部分是与 SwiftUI 的视图有关,其中很多都是由于开发者没有正确的理解和使用 @MainActor 造成的。本文将聊聊 @MainActor 的含义,以及在 SwiftUI 的视图中应用 @MainActor 的技巧和注意事项。

🔎

延伸解读

理解 @MainActor 的本质

@MainActor 是 Swift 并发模型中的特殊 GlobalActor,它确保标记的代码在主线程的串行队列中执行。与 DispatchQueue.main.async 相比,它提供了类型安全和编译时检查,能有效避免数据竞争。开发者应理解其原理,而非仅依赖编译器提示来修复错误。

View 协议与主线程执行的误区

SwiftUI 的 View 协议仅将 body 属性标记为 @MainActor,其他属性和方法并不自动在主线程执行。这解释了为何 PasteButton 等显式标记 @MainActor 的组件在非隔离上下文中会报错。开发者需注意,并非所有视图相关代码都默认运行在主线程。

为视图标注 @MainActor 的利弊

将整个视图类型标注为 @MainActor 可以解决 PasteButton 等组件的初始化问题,并允许直接使用 @State 声明 @MainActor 的可观察对象。但这也强制所有异步方法在主线程执行,可能影响性能。因此,是否标注需根据实际场景权衡,以保持灵活性。

@StateObject 的替代方案

在 Observation 框架下,@StateObject 仍有一项特殊用途:它能在不标注整个视图为 @MainActor 的情况下,安全引入 @MainActor 标注的可观察对象。这是因为 @StateObject 的 wrappedValue 被标记为 @MainActor,且其构造闭包在主线程调用。这为开发者提供了兼顾灵活性与数据安全的临时策略。

❓

Q&A

什么是 @MainActor,它在 Swift 中的作用是什么?

@MainActor 是 Swift 定义的一个特殊 GlobalActor,确保所有标记为 @MainActor 的代码在主线程的串行队列中执行。

在 SwiftUI 中,如何正确使用 PasteButton?

PasteButton 必须在 @MainActor 的上下文中使用,否则会报错。可以通过将相关变量标记为 @MainActor 来解决问题。

为什么 SwiftUI 的 View 协议中的 body 属性被标记为 @MainActor?

因为 body 属性需要在主线程中执行,以确保用户界面正确更新,而其他属性和方法并不保证在主线程执行。

如何在不标注整个视图为 @MainActor 的情况下使用 @StateObject?

可以使用 @StateObject 来引入被 @MainActor 标注的可观察对象,这样可以在不强制标注整个视图的情况下安全使用。

将整个视图标注为 @MainActor 有什么好处?

将整个视图标注为 @MainActor 可以确保视图内所有属性和方法在主线程中执行,简化代码并减少错误。

开发者在使用 Swift 的并发模型时应该注意什么?

开发者应深入理解 Swift 的并发模型,避免仅根据提示逐个修改代码,而是从整体上提升代码质量和可维护性。

🏷️

标签

➡️

继续阅读