如何共享绑定用户会话的Set<AnyCancellable>?Swift Combine开发问题
根因分析
Set<AnyCancellable>属于值类型,每次传递时都会生成独立的拷贝,各个业务模块拿到的是不同的集合实例,修改操作不会同步到原始集合,自然无法实现跨模块共享生命周期的需求。
解决方案
自定义引用类型的封装类包装Set<AnyCancellable>,所有业务模块共享同一个封装类实例,所有订阅存储、取消操作都作用在同一个内部集合上。
1. 实现封装类
import Combine final class SessionCancellables { // 对外暴露只读属性,兼容Combine原生store语法 private(set) var cancellables = Set<AnyCancellable>() /// 添加订阅到当前会话集合 func add(_ cancellable: AnyCancellable) { cancellables.insert(cancellable) } /// 销毁当前会话所有绑定的订阅 func cancelAll() { cancellables.forEach { $0.cancel() } cancellables.removeAll() } }
2. 改造业务模块
将业务类原来持有的Set<AnyCancellable>替换为SessionCancellables实例:
class UserManager { private let sessionCancellables: SessionCancellables init(sessionCancellables: SessionCancellables) { self.sessionCancellables = sessionCancellables } } class UserFeedManager { private let sessionCancellables: SessionCancellables init(sessionCancellables: SessionCancellables) { self.sessionCancellables = sessionCancellables } }
3. 使用示例
// 初始化和用户会话绑定的全局取消集合 let sessionCancellables = SessionCancellables() // 注入到所有需要绑定会话生命周期的业务模块 let userManager = UserManager(sessionCancellables: sessionCancellables) let userFeedManager = UserFeedManager(sessionCancellables: sessionCancellables) // 业务模块内添加订阅示例,两种写法都可以 // 写法1:兼容原生store语法 Just(()) .sink(receiveValue: { _ in }) .store(in: &sessionCancellables.cancellables) // 写法2:调用封装的add方法 let cancellable = Just(()).sink(receiveValue: { _ in }) sessionCancellables.add(cancellable) // 用户登出时统一销毁所有会话相关订阅 sessionCancellables.cancelAll()
可选优化
可以扩展AnyCancellable简化存储写法:
extension AnyCancellable { func store(in sessionCancellables: SessionCancellables) { sessionCancellables.add(self) } } // 使用时直接调用即可 Just(()) .sink(receiveValue: { _ in }) .store(in: sessionCancellables)
内容的提问来源于stack exchange,提问作者Max
相关产品推荐
相关产品推荐

