将订阅存储到订阅集中的原因是什么?

问题描述

合并订阅示例代码段均将结果订阅存储到subscriptions

private var subscriptions = Set<AnyCancellable>()

我们为什么需要这样做?

future
  .sink(receiveCompletion: { print($0) },receiveValue: { print($0) }) 
  .store(in: &subscriptions)

解决方法

我们通常希望将订阅存储在某处,以保持订阅有效。我们通常希望保持几个订阅状态,直到封闭对象被破坏为止,因此将所有订阅存储在单个容器中很方便。

但是,容器不是必须必须Set!它可以是(通常应该是)Array

Cancellable提供了两种 store(in:)方法:

extension Cancellable {
    public func store<C>(in collection: inout C) where C : RangeReplaceableCollection,C.Element == AnyCancellable

    public func store(in set: inout Set<AnyCancellable>)
}

({Array符合RangeReplaceableCollection,但Set不符合,因此它需要自己的方法。)

您已经找到了存储在Set中的那个。但是,您需要 Set的行为吗?将订阅存储在Set中的唯一原因是,如果您需要从集合中有效删除单个订阅,并且该集合可能很大。否则,只需使用Array,如下所示:

class MyObject {

    private var tickets = [AnyCancellable]()

    ...
        future
            .sink(receiveCompletion: { print($0) },receiveValue: { print($0) }) 
            .store(in: &tickets)
,

Cancellable是Combaine提供的协议。

订阅代码(例如发布者,运营商,订阅者调用链)返回一个Cancellable对象,以允许手动取消订阅,并且当对象从内存中释放时,它会取消整个订阅并从中释放其资源记忆。

为实现释放过程的自动化,wen可以将多个订阅存储在AnyCancellable集合中,因此当集合将被取消初始化时,内部的所有订阅都将被取消,相关资源将被释放。

AnyCancellable是一种类型擦除类型,允许将不同的可取消类型存储在同一集合中。

参考

store(in:)将可擦除类型的可取消实例存储到指定的集合中。