Swift Combine: What is AnyCancellable? And how to avoid Memory Leak?

KD Knowledge Diet
3 min readSep 30, 2022

--

Good at development Or a high-level engineer. Developers who are evaluated in the market in such a statement are thorough in memory management. None of the apps should have any memory leaks. In fact, it is not an exaggeration to say that the development of a developer’s skill is the ability to implement what they want while efficiently managing memory. Combine is convenient but you need to consider memory leak.

Problem Statement

Whenever you are calling publisher.sink(), it is going to return a particular subscription.

Now, if you don’t really cancel the subscription, then it can start leaking memory or it will start getting the event from the publisher when you don’t need it.

So, maybe you only needed it for once or twice, but if you don’t cancel your subscription, you will keep receiving the vents which are being originated from the publisher.

Cancel

// Publisher
let publisher = CurrentValueSubject<String, Never>("")

// Subscription
let subscription: AnyCancellable = publisher.sink { value in
print(value)
}

publisher.send("hi") // hi
publisher.send("hello world") // hello world

subscription.cancel()

publisher.send("Change Value!!") // Doesn't work
// Subscription
let subscription = publisher.sink { value in
print(value)
}
subscription.cancel()

The simplest way is to store your subscription to a variable. By doing this, you can use subscription.cancel() method. It cancels the subscription.

Set your subscription to nil

// Publisher
let publisher = CurrentValueSubject<String, Never>("")

// Subscriptoin
var subscription: AnyCancellable? = publisher.sink { value in
print(value)
}

publisher.send("hi") // hi
publisher.send("hello world") // hello world

// Cancel Subscription
subscription = nil

publisher.send("Change Value!!") // Doesn't work
// Cancel Subscription 
subscription = nil

You can cancel your subscription just by making it optional and setting its value to nil.

What is AnyCancellable?

var subscription: AnyCancellable

Your guess is right. AnyCancellable is a data type that can hold any subscription. Nothing more to explain.

Why usually declaring AnyCancellable on Global Scope?

import UIKit
import Combine

class ViewController: UIViewController {

// Publisher
let publisher = CurrentValueSubject<String, Never>("")
var subscription: AnyCancellable?

override func viewDidLoad() {
super.viewDidLoad()

// Subscriptoin
subscription = publisher.sink { value in
print(value)
}

publisher.send("hi") // hi
publisher.send("hello world") // hello world

subscription = nil

publisher.send("Change Value!!") // Doesn't work

}

}
class ViewController: UIViewController {

var subscription: AnyCancellable?

override func viewDidLoad() {
super.viewDidLoad()
...
}

}

You probably have seen this pattern multiple times. It’s just simple. This is because when function execution is once finished, it’s gone from memory forever. That’s why you need to declare AnyCancellable or your subscriptions in your global scope.

Save Multiple Subscriptions

import UIKit
import Combine

class ViewController: UIViewController {

var subscriptions: Set<AnyCancellable> = []

// Publishers
let publisher = CurrentValueSubject<String, Never>("")
let publisher2 = CurrentValueSubject<String, Never>("")

override func viewDidLoad() {
super.viewDidLoad()

// Subscription
publisher.sink { value in
print(value)
}
.store(in: &subscriptions)

// Subscription2
publisher2.sink { value in
print(value)
}
.store(in: &subscriptions)

publisher.send("hi") // hi
publisher.send("hello world") // hello world

subscriptions.removeAll()

publisher.send("Change Value!!") // Doesn't work

}

}
.store(in: &subscriptions)

subscriptions.removeAll()

In order to save your subscriptions, you need to use this method .store(in: &set).

To cancel all the subscriptions, just call subscriptions.removeAll().

Conclusion

  • Save the subscription to AnyCancellable variable and call cancel()
  • When you have multiple publishers, remove them from your Set<AnyCancellable>

--

--

KD Knowledge Diet

Software Engineer, Mobile Developer living in Seoul. I hate people using difficult words. Why not using simple words? Keep It Simple Stupid!