Swift 6跨全局Actor调用协议方法引发数据竞争错误的解决问询
问题场景
代码中MyProtocol由GlobalActor隔离,Controller协议由ControllerActor隔离,在Controller的扩展方法doControllerWork中调用await myProtocol?.doSomething()时,出现以下错误:
Sending global actor 'ControllerActor'-isolated value of type 'any MyProtocol' with later accesses to global actor 'GlobalActor'-isolated context risks causing data races.
需求是保持两个协议各自的Actor隔离,同时共享doControllerWork方法。
解决方案
方案1:显式切换到目标Actor上下文执行调用
修改扩展方法,通过GlobalActor.shared.run将方法调用包裹在GlobalActor的隔离上下文中执行:
extension Controller { func doControllerWork() async { await GlobalActor.shared.run { await myProtocol?.doSomething() } } }
原理:强制在GlobalActor的隔离域内访问MyProtocol的方法,明确隔离上下文,消除跨Actor访问的风险。
方案2:显式指定属性的隔离域
修改Controller协议,将myProtocol属性的隔离域指定为GlobalActor:
@ControllerActor protocol Controller { @GlobalActor var myProtocol: MyProtocol? { get } }
之后原扩展方法无需修改即可正常运行:
extension Controller { func doControllerWork() async { await myProtocol?.doSomething() } }
原理:Swift会自动处理从ControllerActor到GlobalActor的上下文切换,确保访问myProtocol及其方法时处于正确的隔离域,避免数据竞争风险。
错误原因说明
原代码中,myProtocol作为ControllerActor隔离域内的属性被持有,但它的方法属于GlobalActor隔离域,直接跨Actor调用会导致Swift并发检查机制检测到潜在的数据竞争风险,因此抛出警告。
内容的提问来源于stack exchange,提问作者Sorin Lica

