Swift6下NSBundleResourceRequest两种写法编译差异原因咨询
Swift 6下Actor中NSBundleResourceRequest两种写法的编译差异解析
报错代码示例
final actor ODRRequest { let request = NSBundleResourceRequest(tags: ["bla"]) func startRequest() { Task {[unowned self] in let available = await request.conditionallyBeginAccessingResources() if available { updateState(.available) } } } }
编译报错:向非隔离上下文发送带有后续访问的actor隔离类型'NSBundleResourceRequest'值,存在数据竞争风险
正常运行代码示例
private func startRequest() { request.conditionallyBeginAccessingResources {[unowned self] available in Task { if available { await updateState(.available) } } } }
差异原因解析
第一种写法报错的核心逻辑
- Swift 6启用了严格的
Sendable协议检查,要求跨隔离上下文传递的类型必须符合Sendable,以此避免数据竞争风险。 NSBundleResourceRequest未被苹果标记为Sendable类型,说明它不具备线程安全的跨上下文传递能力。- 在Actor的隔离方法
startRequest中创建的默认Task,会在非隔离的全局执行上下文运行。你在Task闭包里捕获self并访问self.request,等同于把Actor隔离的request实例发送到了非隔离上下文——编译器无法保证线程安全,因此抛出报错。
第二种写法正常编译的逻辑
- 调用
request.conditionallyBeginAccessingResources(_:)的操作完全在Actor的隔离上下文内完成,此时对request的访问符合Actor的隔离规则,不存在跨上下文传递的问题。 - 回调闭包仅捕获了
self和available值,没有将request实例带出Actor的隔离边界。后续Task仅通过await updateState(.available)切换回Actor的隔离上下文执行状态更新,整个流程完全符合Swift 6的隔离检查规则。
内容的提问来源于stack exchange,提问作者Andriy Gordiychuk
相关产品推荐
相关产品推荐

