When you subscribe to a publisher in Combine, the subscription that gets created needs to be kept alive somewhere otherwise it gets deallocated immediately and the pipeline dies. This is what cancellables is for — when you call .store(in: &cancellables) you're essentially telling Swift "keep this subscription alive, don't deallocate it". As long as the subscription lives inside the cancellables set it stays active and the subscriber keeps listening for incoming values. Since cancellables is a property on your ViewController it lives for as long as the ViewController itself lives, meaning all your subscriptions stay active for the entire lifetime of the screen. And when the ViewController eventually gets deallocated, cancellables gets deallocated with it which automatically cancels all subscriptions and cleans everything up — so memory management essentially takes care of itself. This is why with an async publisher like a network call not storing the subscription means you'll never receive any values, because by the time the response comes back the subscription is already gone and there's nothing left listening for it.

Concept

In Combine, subscriptions are represented by:

AnyCancellable

A subscription remains active only as long as it is retained in memory.

If the reference is not stored, the subscription is immediately cancelled.


Key Idea

No reference = subscription cancelled

Combine does not retain subscriptions automatically.

Developers must explicitly store them to keep streams alive.


Storing Subscriptions

Subscriptions are typically stored in:

var cancellables = Set<AnyCancellable>()

Example:

publisher
    .sink { value in
        print(value)
    }
    .store(in: &cancellables)

This ensures the subscription stays active for the lifetime of the owner (e.g., ViewController).