Swift Global Actor 完全指南

原文:Global actor in Swift Concurrency explained with code examples -- SwiftLee

什么是 Global Actor?

概念 一句话解释
Actor 一种引用类型,串行化地执行对其状态的访问,天然线程安全。
Global Actor 全局唯一的 Actor,可被标注到 任意函数 / 属性 / 类型,让所有访问都在同一条串行队列上执行。

一句话:把「线程同步」这件事从手动加锁升级为「编译器帮你保证」。

系统自带:@MainActor

最常见、也是 iOS 开发者天天打交道的全局 Actor。

swift 复制代码
// 1. 标注函数 → 保证主线程
@MainActor
func updateUI() {
    label.text = "Done"      // 永远在主线程执行
}

// 2. 标注属性 → 所有读写都在主线程
@MainActor
var titles: [String] = []

// 3. 标注整个类 → 类内所有成员默认主线程
@MainActor
final class ContentViewModel {
    var titles: [String] = []
}

凡是 UI 更新、KVO、NotificationCenter 的 post/observe,都建议加上 @MainActor,省去手动 DispatchQueue.main.async。

自定义 Global Actor:三步走

当你需要把 一类业务逻辑 放到同一条串行执行队列时(如图像处理、磁盘缓存、音频渲染...),自建全局 Actor 是利器。

Step 1:声明 Actor + @globalActor

swift 复制代码
@globalActor
actor ImageProcessing {
    static let shared = ImageProcessing()   // 必须实现
    private init() {}                      // ✅ 建议私有,防止乱 new
}
  • @globalActor 告诉编译器:这是一个「全局单例」Actor。
  • 必须提供 static let shared,否则会编译错误。
  • 把 init() 设为 private,避免外部 ImageProcessing() 创建新实例。

Step 2:贴标签即可用

swift 复制代码
// 1. 标注类 → 类内所有成员自动走 ImageProcessing 队列
@ImageProcessing
final class ImageCache {
    private var store: [URL: Data] = [:]

    func store(_ data: Data, for url: URL) {
        store[url] = data          // 自动线程安全
    }
}

// 2. 标注单个函数
@ImageProcessing
func applyFilter(_ image: UIImage) -> UIImage {
    // 耗时滤镜计算
    return image
}

Step 3:跨 Actor 调用

swift 复制代码
@MainActor
class EditorViewModel {
    private let cache = ImageCache()   // 也在 ImageProcessing 上

    func saveThumbnail(for url: URL) async {
        let image = UIImage(data: try! Data(contentsOf: url))!
        let filtered = await applyFilter(image)   // ✅ 跨 Actor,用 await
        await cache.store(filtered.pngData()!, for: url)
    }
}
  • 任何跨 Actor 访问都要 await,编译器会强制你遵守。
  • 不再需要手动 DispatchQueue / NSLock,彻底告别数据竞争。

常见疑问 & 最佳实践

问题 解答
可以用在 struct / enum 吗? ✅ 可以,只要挂上 @YourGlobalActor。
能继承吗? ❌ Actor 是引用类型,不能继承;但你可以把 Actor 包装在类里。
相关推荐
茶底世界之下2 小时前
类型擦除之后,Metal 滤镜组合为什么不能只执行一个 Filter?
ios·swift
茶底世界之下1 天前
Metal 冷启动并发下,Pipeline Cache 为什么必须合并在途编译
ios·swift
黑科技iOS上架3 天前
双引擎解决oc/swift开发引用加固难题
开发语言·ios·swift·审核·ios混淆·执行程序差异化
传奇开心果编程4 天前
【SwiftUI提高练中学】第13课 实时活动与灵动岛:ActivityKit 实战
学习·ui·ios·swiftui·swift
AC赳赳老秦4 天前
数据采集全链路审计留痕:用 OpenClaw 实现合规审计与追溯
开发语言·汇编·python·php·swift·deepseek·openclaw
传奇开心果编程5 天前
【SwiftUI入门练中学】第17课 通知与后台任务
学习·ui·ios·swiftui·swift
逐流人6 天前
Ceph对象存储与文件系统存储管理:从RADOS网关、S3与Swift到CephFS快照同步
linux·运维·ceph·云原生·云计算·swift·rados
传奇开心果编程6 天前
【SwiftUI入门练中学】第7课 动画与手势:让界面更灵动
学习·macos·ui·ios·swiftui·swift