Anycancellable
Any Cancellable
Mind Map
RxSwift equivalent of disposeBag
Initialize
private var cancellables = Set<AnyCancellable>()
private var cancellable = AnyCancellable?
Deinitialize
deinit {
cancellables.removeAll()
cancellable = nil
}
Syntax
class Name {
var cancellable = Set<AnyCancellable>()
func something() {
publisher
.sink { val in
self.mainLabel.text = val
   }
   .store(in: &cancellable)
}
}
vs
You can't use this code even though you're storing the value of sink
return type AnyCancellable
let anycancel = publisher
.sink { val in
self.mainLabel.text = val
}
Since the closure is a function which is of type reference.
So it would just not hold the reference of self to even subscribe to the publisher. As we are still in function scope of setupPublisherSubscriber
Even though we didn't use [weak self] and opted for strong reference it won't subscribe unless the AnyCancellable
returned by sink
or assign(to:)
isn't hold on class level reference.
This could be also attributed to Hot vs Cold observable phenomenon in RxSwift
Weak, unowned and self in combine
Subscription lifecycle
Note
One thing I have observed while making my network manager code for Combine in its own file. If I use a weak reference in the sink
block then the subscription weren't initialized. And the moment I use no capture list in the sink block, it automatically publishes all the changes in the reactive chain.
It is because maybe I'm accessing the combine function of a class instance in a function. Which limits its scope of class reference.
Because if I use a singleton instance of Network Manager
it just works fine.
I think so after my 15 mins debugging, I believe because I create the reference of Network Manager
in a function scope of the consumer. The Arc or anycancellables
is de-initializing itself or subscription is ending quickly.
.print()
operator really helped how to narrow down the publisher - subscription chain internal events.
More Learning Nov 2023
Very important
if a classA -> Instantiates classB, where classB has Cancellables
references but classA should hold onto the reference of classB in a variable so that the subscription stays alive and retained.
class classA {
var classB: ClassB?
// This will hold the subscriptions lifecycle
normalInstantiate() {
classB = ClassB()
}
// This won't, this will get deallocated quickly.
func assignedInstantiate() {
let _ = ClassB()
}
}
class classB {
private var cancellables = Set<AnyCancellable>()
private let publisher: PassthroughSubject<EventRepresentable, Never>
func subscriptions() {
NotificationCenter
      .default
      .publisher(for: AVPlayerItem.mediaSelectionDidChangeNotification)
      .receive(on: eventQueue)
      .sink { doSomething() }
      .store(in: &cancellables)
publisher
      .receive(EventsType.self, on: DispatchQueue.main) { event in
        if case .noEvent = event {
          print("Hello No Event!@")
        }
      }
      .store(in: &cancellables)
}
}
Managing self and cancellable references when using Combine
what-exactly-is-a-combine-anycancellable