译者 | 明知山
策划 | Tina
曾在 Crashlytics 和苹果工作的 Swift 开发者 Matt Massicotte 最近发布了一个 Github 代码库,收集了许多有用的技巧,便于更轻松地使用 Swift 并发性和解决经常出现的问题,同时提到了人们可能容易掉入的常见陷阱。
自 async/await
的出现和 Swift 5.5 支持 actor 以来,Swift 并发编程一直在持续发展,直到在 Swift 5.10 中引入了完整的数据隔离和结构化并发。掌握所有新的并发特性本身就是一项相当艰巨的任务,而雪上加霜的是,Swift 并发原语需要与之前的技术和库(如 Grand Central Dispatch (GCD))共存。
在这种背景下,Massicotte 的这个项目库旨在记录和分享在使用 Swift 并发性和远离 GCD 时可能面临的解决方案和危险。
Swift 并发性可能真的很难用好。我认为记录和分享人们在使用过程中可能遇到的解决方案和危险会对我们有所裨益。我绝对不是说这些东西已经很全面或所提出的解决方案足够好。我也在学习。也非常欢迎大家参与贡献,尤其是提出问题!
这个代码库分为几个部分,每个部分都围绕一个主题,从创建异步上下文的基本任务到处理协议、隔离、SwiftUI 等问题。
例如,Massicotte 解释说,在 SwiftUI 中,有关并发性的一个棘手的问题是,只有 SwiftUI View
的 body
访问器是 MainActor
安全的,这使得在 View
中声明的任何其他函数或属性都是非隔离的,并且容易发生竞态条件。他提出的解决方案是显式声明更复杂视图的 @MainActor
属性:
@MainActor
struct MyView: View {
var body: some View {
Text("Body")
}
}
类似地,通过协议正确处理并发性可能会很复杂,正如 Massicotte 所描述的那样,你希望使一个MainActor
隔离的类型符合你无法控制其定义的协议。
可能你也知道,actor 需要确保只有async
方法可以从外部访问其状态,在这种情况下,编译器可以确保永远不会发生竞态条件。因此,如果一个 actor 隔离的类型,例如,只能在MainActor
内部使用的类型,必须符合包含非 async 方法的协议,你就需要多加注意。最简单的解决方案是使用nonisolated
关键字指示编译器,采用“非隔离”一致性,或者你也可以优先使用委托来绕过这个问题。
如前所述,Massicotte 描述了许多问题以及可能的解决方案。即使这个代码库所建议的解决方案可能并不完全令人满意,但肯定会增加你对使用 Swift 并发性时可能出错的各种情况的认识,因此它会是一个非常有用的资源。
查看英文原文:
https://www.infoq.com/news/2024/04/swift-concurrent-recipes/
声明:本文为 InfoQ 翻译,未经许可禁止转载。