如何实现Swift Actor隔离状态的可观察性?
让Actor的隔离状态支持可观察性(适配SwiftUI等场景)
初始Actor定义
我们有一个泛型Actor,内部包含被隔离的状态属性:
actor MyActor<State> { private var state: State private init(initialState: State) { self.state = initialState } public func message(param: Int) { // 修改state的逻辑 ... } }
需求与限制
现在需要观察这个被隔离的state属性,用于SwiftUI视图状态或其他场景,但当前Observation框架的@Observable宏暂不支持Actor,无法直接使用该方案。
尝试基于Combine Publisher的实现
一种思路是让Actor成为Combine Publisher,对外发布内部状态:
修改后的Actor代码
将原state替换为CurrentValueSubject:
actor MyActor<State> { private var _state: CurrentValueSubject<State, Never> private init(initialState: State) { self._state = .init(initialState) } public func message(param: Int) { // 修改_state的逻辑 ... } }
实现Publisher协议的尝试
为了让Actor符合Publisher协议,添加如下扩展:
extension MyActor: Publisher { public typealias Output = State public typealias Failure = Never public func receive<S>( subscriber: S ) where S : Subscriber, Never == S.Failure, State == S.Input { _state.receive(subscriber: subscriber) } }
但此时编译器会抛出错误:
Actor-isolated instance method 'receive(subscriber:)' cannot be used
to satisfy nonisolated protocol requirement
取巧的错误修复方案
可以通过nonisolated修饰方法,并借助assumeIsolated来消除错误:
extension MyActor: Publisher { public typealias Output = State public typealias Failure = Never nonisolated public func receive<S>( subscriber: S ) where S : Subscriber, Never == S.Failure, State == S.Input { // 注:可能需要将`_state`声明为nonisolated assumeIsolated { this in this._state.receive(subscriber: subscriber) } } }
这样修改后,只需通过receive(on:)操作符将值分发切换到主线程,就能把这个Actor集成到@Observable类型或符合ObservableObject协议的类型中,像常规模型一样在SwiftUI中使用。但这种实现方式比较取巧,不确定线程安全性是否合规。
寻求其他实现思路
除了上述方案,是否还有其他实现Actor可观察性的合理思路?或者最终结论应该是:不要使用Actor,改用@MainActor和final class?
内容的提问来源于stack exchange,提问作者CouchDeveloper
相关产品推荐
相关产品推荐

