We usually want to store the subscription somewhere, to keep the subscription alive. We often want to keep several subscriptions alive until the enclosing object is destroyed, so it's convenient to store all the subscriptions in a single container.
However, the container does not have to be a Set
! It can be (and usually should be) an Array
.
Cancellable
provides two store(in:)
methods:
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
conforms to RangeReplaceableCollection
, but Set
does not, so it needs its own method.)
You have found the one that stores into a Set
. But do you need the behavior of a Set
? The only reason to store your subscriptions in a Set
is if you need to efficiently remove a single subscription from the set, and the set may be large. Otherwise, just use an Array
, like this:
class MyObject {
private var tickets = [AnyCancellable]()
...
future
.sink(receiveCompletion: { print($0) }, receiveValue: { print($0) })
.store(in: &tickets)
I think the reason you often see code that uses a Set<AnyCancellable>
is because most Swift programmers are much more familiar with Set
and Array
than with RangeReplaceableCollection
. When Xcode offers to autocomplete store
to take either a Set
or a RangeReplaceableCollection
, you're going to pick the Set
version if you don't know that an Array
is a RangeReplaceableCollection
.