Objective-C
KVO
ARC
removeObserver
memory-management

KVO and ARC how to removeObserver

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

ARC manages object memory, but it does not automatically solve old-style KVO observer registration problems for you. If you register an observer manually with addObserver, you are still responsible for balancing that with correct observer removal or using a safer modern API that manages observation tokens for you.

The Old KVO Pattern Requires Explicit Removal

With classic KVO, you register an observer and later remove it. If the observed object or the observer goes away while the observation is still active, you can crash.

Objective-C example:

objective-c
1[self.person addObserver:self
2              forKeyPath:@"name"
3                 options:NSKeyValueObservingOptionNew
4                 context:NULL];

Later, you must remove it:

objective-c
[self.person removeObserver:self forKeyPath:@"name"];

ARC will release objects when retain counts drop, but it does not automatically infer when your observation relationship should end.

Where Removal Should Happen

In older Objective-C code, removal often happens in dealloc or when the observed object changes.

objective-c
- (void)dealloc {
    [self.person removeObserver:self forKeyPath:@"name"];
}

This is only safe if you are sure the observer was actually added and has not already been removed. Double removal can also cause exceptions in classic KVO code.

That is why many legacy KVO bugs are not memory leaks, but lifecycle mismatch bugs.

Safer Modern Approach in Swift

Modern Swift offers a safer token-based observation API. Instead of manually balancing addObserver and removeObserver, keep the returned NSKeyValueObservation alive for as long as observation should continue.

swift
1import Foundation
2
3class Person: NSObject {
4    @objc dynamic var name: String = "Ada"
5}
6
7let person = Person()
8var observation: NSKeyValueObservation?
9
10observation = person.observe(\.name, options: [.new]) { object, change in
11    print(change.newValue ?? "")
12}
13
14person.name = "Grace"
15observation = nil

When the observation token is released, the observation stops. This is far less error-prone than classic manual removal.

ARC and KVO Solve Different Problems

This is the core concept:

  • ARC manages object lifetime
  • KVO manages change notifications between objects

They interact, but they are not the same system. You can have perfectly ARC-managed objects and still crash because an observer relationship outlives one participant.

That is why "I use ARC" is not an answer to observer cleanup.

Common Legacy Scenarios That Break

Common failure patterns include:

  • observing one object, then replacing it without removing the old observation
  • removing observers in the wrong order during controller teardown
  • adding the same observer twice and removing it once
  • assuming ARC will clean observation automatically in old KVO style

These issues are especially common in view-controller code that observes models, scroll views, or AVPlayer state.

Keep Observation Lifetime Explicit

A good mental model is that observation should be owned by the same object that needs the updates. When the owner goes away, the observation should go away too. Token-based KVO in Swift makes that ownership model much easier to express than scattered manual removal calls across several lifecycle methods.

Common Pitfalls

  • Assuming ARC removes old-style KVO observers automatically.
  • Removing an observer twice and triggering a different crash.
  • Forgetting to remove an observer when the observed object changes, not only on deallocation.
  • Mixing legacy addObserver APIs with newer token-based APIs without a consistent pattern.
  • Using KVO when a delegate, closure, or notification would be simpler and safer.

Summary

  • ARC does not replace correct KVO observer management.
  • Old-style KVO requires explicit observer removal.
  • Modern token-based observation in Swift is usually safer than manual removeObserver calls.
  • Most KVO crashes come from lifecycle mismatches, not from memory leaks alone.
  • If you must use KVO, choose one observation style and manage its lifetime deliberately.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.