You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何以线程安全方式监听UIPasteboard?Swift 6适配问题

Swift 6下@Observable类修改状态的解决方案

Swift 6中@Observable会将类隐式转换为actor隔离类型,状态修改必须在对应actor的隔离上下文内执行。原代码中通知闭包未正确绑定隔离上下文,导致无法修改images属性,以下是两种可行方案:

方案一:异步机制(推荐,适配Swift 6并发模型)

通过Task自动切换到@Observable类的actor隔离上下文,安全修改状态,同时避免循环引用:

@Observable
final class ImageClipboard {
    var images: [SelectableImage] = []
    
    init() {
        NotificationCenter.default.addObserver(forName: UIPasteboard.changedNotification, object: nil, queue: .main) { [weak self] _ in
            guard let self = self, let pasteboardImages = UIPasteboard.general.images else { return }
            let newImages = pasteboardImages.map(SelectableImage.init)
            
            // 异步进入actor上下文修改状态
            Task {
                self.images.append(contentsOf: newImages)
            }
        }
    }
}

这种方式无需硬编码主线程依赖,适配@Observable类默认的actor隔离规则,后续代码变更时兼容性更好。

方案二:同步机制(显式绑定主线程)

若确定所有操作都在主线程执行,可将类显式标记为@MainActor,此时通知闭包运行在主线程(已指定queue: .main),可直接修改状态:

@MainActor
@Observable
final class ImageClipboard {
    var images: [SelectableImage] = []
    
    init() {
        NotificationCenter.default.addObserver(forName: UIPasteboard.changedNotification, object: nil, queue: .main) { [weak self] _ in
            guard let self = self, let pasteboardImages = UIPasteboard.general.images else { return }
            let newImages = pasteboardImages.map(SelectableImage.init)
            
            // 直接修改状态,当前已在MainActor上下文
            self.images.append(contentsOf: newImages)
        }
    }
}

该方案更简洁,适合UI相关的剪贴板监听场景,所有状态变更都在主线程完成,避免跨线程UI同步问题。

通用注意事项

  • 必须使用[weak self]捕获,避免NotificationCenter持有闭包导致的循环引用,确保类实例能正常释放。
  • 处理剪贴板内容时增加空值判断,避免UIPasteboard.general.images为nil时引发异常。

内容的提问来源于stack exchange,提问作者Nitesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 00:12:48