Removing Observers Safely
Avoid leaks and crashes from stale observers.
Removing Observers Safely is a free Swift Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Removing Observers Safely
Observers must be removed when no longer needed. A dangling observer can fire after its owner is gone, causing bugs or, with old APIs, crashes.
Why Removal Matters
Selector-based observers historically had to be removed in deinit to avoid messaging a deallocated object.
import Foundation
class Watcher: NSObject {
override init() { super.init() }
deinit { NotificationCenter.default.removeObserver(self) }
}
print("Removes itself on deinit")removeObserver(self)
Calling removeObserver(self) unregisters every observation made by that object in one call.
import Foundation
class VM: NSObject {
func stop() { NotificationCenter.default.removeObserver(self) }
}
VM().stop()
print("Removed all observations for self")Removing a Specific Name
You can remove only one observation by passing the name and object, leaving others intact.
import Foundation
let center = NotificationCenter.default
let obj = NSObject()
let name = Notification.Name("ping")
center.removeObserver(obj, name: name, object: nil)
print("Removed a specific observation")Token-Based Observers
The closure-based addObserver returns an opaque token. Keep it, and remove the observer with that token.
import Foundation
let center = NotificationCenter.default
let name = Notification.Name("ping")
let token = center.addObserver(forName: name, object: nil, queue: nil) { _ in }
center.removeObserver(token)
print("Removed via token")Storing the Token
Store the token in a property so it lives as long as you want the observation, and remove it when done.
import Foundation
class Model {
var token: NSObjectProtocol?
func start() {
token = NotificationCenter.default.addObserver(
forName: Notification.Name("x"), object: nil, queue: nil) { _ in }
}
func stop() {
if let t = token { NotificationCenter.default.removeObserver(t) }
}
}
let m = Model(); m.start(); m.stop()
print("Lifecycle managed")Automatic Cleanup with deinit
Remove the token in deinit so the observation ends when the owner is deallocated.
import Foundation
class Owner {
var token: NSObjectProtocol?
deinit { if let t = token { NotificationCenter.default.removeObserver(t) } }
}
print("Token removed on deinit")Modern Lifetime Note
On recent runtimes, observers added with the block API are auto-removed when the token deallocates, but explicit removal is still the safe, clear choice.
import Foundation
// Holding the token in a property controls its lifetime.
class C { var token: NSObjectProtocol? }
print("Token lifetime equals observation lifetime")Avoiding Retain Cycles
If a closure observer captures self strongly, use [weak self] to avoid a retain cycle that prevents deallocation.
import Foundation
class VM {
var token: NSObjectProtocol?
func start() {
token = NotificationCenter.default.addObserver(
forName: Notification.Name("x"), object: nil, queue: nil) { [weak self] _ in
self?.handle()
}
}
func handle() { print("handled") }
}
VM().start()Double Removal Is Safe
Removing an observer that is already gone is harmless, so defensive cleanup will not crash.
import Foundation
let center = NotificationCenter.default
let obj = NSObject()
center.removeObserver(obj)
center.removeObserver(obj) // no harm
print("Safe to remove twice")Best Practice Summary
Prefer token-based closures, store the token, remove it in deinit, and capture self weakly. This keeps observation lifetimes correct.
import Foundation
class Best {
var token: NSObjectProtocol?
deinit { token.map { NotificationCenter.default.removeObserver($0) } }
}
print("Followed best practices")Quick Check
How do you remove a closure-based observer added with addObserver(forName:...)?
Recap
Always remove observers you no longer need. Use removeObserver(self) for selector observers and the returned token for closure observers, store the token, clean up in deinit, and capture self weakly. Next: how the observer pattern compares to alternatives.
Frequently asked questions
Is the “Removing Observers Safely” lesson free?
Yes — the full text of “Removing Observers Safely” is free to read here on the web, and the Swift Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Swift Academy course, upgrade to CoddyKit PRO.
What will I learn in “Removing Observers Safely”?
Avoid leaks and crashes from stale observers. You practise Swift Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Swift Academy?
No prior experience is required. Swift Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Removing Observers Safely” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Swift Academy lesson?
Yes. Every Swift Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Posting and Observing Notifications
- Notification userInfo Payloads
- Removing Observers Safely
- The Observer Pattern Alternatives