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

Actor隔离可变属性传入async函数报错,如何解决?

解决Actor隔离上下文调用Publisher转async-await扩展的问题

报错的核心原因是Actor隔离的属性无法以inout形式传递给async函数。因为async函数可能会挂起,挂起期间Actor的状态(比如anyCancellables集合)可能被其他同Actor任务修改,破坏了Actor的线程安全隔离保证,因此Swift编译器直接禁止这种操作。

以下是两种可行的解决方案:

方案一:移除外部Cancellables依赖,利用结构化并发自动管理订阅

这种方案不需要外部维护Set<AnyCancellable>,而是通过任务取消机制自动管理订阅生命周期,更符合结构化并发的设计理念:

extension Publisher where Failure == Never {
    func waitFor(predicate: @escaping (Output) -> Bool) async {
        await withCheckedContinuation { continuation in
            // 创建订阅
            let cancellable = sink { value in
                if predicate(value) {
                    continuation.resume()
                }
            }
            
            // 监听当前任务取消状态,任务取消时自动取消订阅
            Task {
                await Task.currentTask?.isCancelled
                cancellable.cancel()
            }
        }
    }
}

使用方式简化为:

@MainActor
class ThingClass {
    let intPTS = PassthroughSubject<Int, Never>()
    
    func doSomething() async {
        await intPTS.waitFor { $0 == 10 }
        print("intPTS is 10 now!")
    }
}

方案二:保留外部Cancellables集合,避免inout传递

如果必须依赖外部维护的Set<AnyCancellable>,可以修改扩展返回订阅对象,由Actor内部自行插入集合,避免inout传递:

extension Publisher where Failure == Never {
    func convertToAsync(predicateClosure: @escaping (Output) -> Bool) async -> AnyCancellable {
        await withCheckedContinuation { continuation in
            let cancellable = sink { value in
                if predicateClosure(value) {
                    continuation.resume(returning: cancellable)
                    cancellable.cancel() // 满足条件后主动取消订阅,避免内存泄漏
                }
            }
        }
    }
}

使用方式:

@MainActor
class ThingClass {
    let intPTS = PassthroughSubject<Int, Never>()
    var anyCancellables: Set<AnyCancellable> = []
    
    func doSomething() async {
        let cancellable = await intPTS.convertToAsync { $0 == 10 }
        anyCancellables.insert(cancellable)
        print("intPTS is 10 now!")
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 22:52:42