如何共享套装<AnyCancellable>?



我有一个绑定到用户会话的Set<AnyCancellable>。任何绑定到用户会话的订阅都会被添加到这个集合中。我希望能够传递这个集合,以便其他东西可以将其逻辑绑定到用户的会话。我遇到的问题是,Set是一个结构体,通过inout传递它不会真正工作。有没有更好的方法来共享Set<AnyCancellable>?

下面是我要做的一个例子:

class UserManager {
private var cancellable: Set<AnyCancellable>
init(cancellable: Set<AnyCancellable>) {
self.cancellable = cancellable
}
}
class UserFeedManager {
private var cancellable: Set<AnyCancellable>
init(cancellable: Set<AnyCancellable> {
self.cancellable = cancellable
}
}
let cancellable = Set<AnyCancellable>()
let userManager = UserManager(cancellable)
let userFeedManager = UserFeedManager(cancellable)
// ... Later, once the user signs out, clean up any work 
// started by the UserManager or the UserFeedManager
cancellable.forEach { $0.cancel() }
cancellable.removeAll()

组合订阅的生存期与订阅返回的AnyCancellable绑定。因此,如果对Set<AnyCancellable>的最后一个引用被释放,那么存储在Set中的所有AnyCancellable也将被释放,因此所有订阅将被取消。

所以与其从外部传入Set<AnyCancellable>并手动调用
cancellable.forEach { $0.cancel() }
cancellable.removeAll()

,您应该简单地在您的UserManager上公开Set,并且每当您的用户退出时,只需确保您释放了以前的UserManager对象并创建了一个新对象。这将确保自动取消以前的所有订阅。

class UserManager {
var cancellable = Set<AnyCancellable>()
}

这样,您只需要传递相同的UserManager实例,直到用户登录,并在用户注销时创建和销毁实例。

我建议注入一个协议,比如

protocol CancellablesHolder {
func add(cancellable: AnyCancellable)
}

并使UserManager符合该协议:

class UserManager {
private var cancellable: Set<AnyCancellable>
}
extension UserManager: CancellablesHolder {
func add(cancellable: AnyCancellable) {
cancellable.add(cancellable)
}
}

使用上面的定义,您可以

class UserFeedManager {
private var cancellablesHolder: CancellablesHolder
init(cancellablesHolder: CancellablesHolder) {

通过这种方式,您可以对CancellablesHolder的客户端隐藏实现细节,并且您也可以透明地在路上传递UserManager,而不会暴露给客户端,因为客户端不一定关心实际类型。

这会导致耦合度的降低,以及实现可取消对象存储的灵活性,因为消费者不知道,也不关心存储机制。

相关内容

最新更新