Introduction
Swift manages the memory used by class instances through Automatic Reference Counting (ARC). Rather than relying on a garbage collector that periodically scans and frees unused memory (as Java or Kotlin do), the Swift compiler automatically inserts retain and release calls at compile time, tracking how many strong references point to each instance. When that count drops to zero, the instance is deallocated immediately and deterministically. Structs and enums are value types and are not managed by ARC at all, since they are copied rather than referenced.
Cricket analogy: ARC is like a scorer who tallies exactly how many fielders are still 'holding' a run-out appeal in real time as it happens, instead of a match referee sweeping through footage afterward like a garbage collector; once no fielder holds the appeal, it's discarded immediately, while a run tally (a value type) is simply copied onto the scoreboard.
Syntax
class Person {
let name: String
init(name: String) { self.name = name }
deinit { print("\(name) is being deinitialized") }
}
var person1: Person? = Person(name: "Alice")
var person2 = person1 // strong reference, retain count increases
person1 = nil // one strong reference removed
person2 = nil // last strong reference removed, deinit runsExplanation
Every class instance keeps an internal count of how many strong references point to it. Assigning an instance to a new variable, constant, or property increases that count; setting a reference to nil or letting it go out of scope decreases it. Once the count reaches zero, ARC deallocates the instance and calls its deinit. This system works well for simple ownership graphs, but two instances that hold strong references to each other create a retain cycle: neither count ever reaches zero, so neither instance is ever deallocated, producing a memory leak.
Cricket analogy: Each time a fielder joins a run-out appeal it's like incrementing ARC's reference count, and when a fielder steps back it decrements; when Virat Kohli and a bowler both hold strong references to each other's end-of-over review, neither count reaches zero, and the appeal leaks forever — a retain cycle.
Example
class Owner {
let name: String
var pet: Pet?
init(name: String) { self.name = name }
deinit { print("\(name) deinitialized") }
}
class Pet {
let name: String
weak var owner: Owner? // weak breaks the retain cycle
init(name: String) { self.name = name }
deinit { print("\(name) deinitialized") }
}
var owner: Owner? = Owner(name: "Sam")
var pet: Pet? = Pet(name: "Rex")
owner?.pet = pet
pet?.owner = owner
owner = nil
pet = nilOutput
Sam deinitialized
Rex deinitializedKey Takeaways
- ARC automatically manages memory for class instances by tracking strong reference counts; structs and enums are value types and are unaffected by ARC.
- Swift has no garbage collector — deallocation happens deterministically the instant the strong reference count hits zero.
- Two class instances holding strong references to each other form a retain cycle, leaking memory since neither is ever deallocated.
- weak references are optional and automatically become nil when the referenced instance is deallocated.
- unowned references are non-optional and assume the referenced instance always exists; using one after deallocation causes a crash.
- Closures that capture self strongly can also create retain cycles; use a [weak self] or [unowned self] capture list to avoid them.
Practice what you learned
1. What does ARC stand for in Swift?
2. Which Swift types are NOT managed by ARC?
3. What is a retain cycle?
4. How does a weak reference differ from an unowned reference?
5. Does Swift use a garbage collector like Java or Kotlin?
Was this page helpful?
You May Also Like
Classes in Swift
Classes are reference types in Swift that support inheritance and are managed automatically via ARC.
Structs vs Classes in Swift
Structs use value semantics while classes use reference semantics — the defining choice you make for every custom Swift type.
Closures in Swift
Understand closures as self-contained blocks of functionality that capture and store references to surrounding variables.
Properties and Methods in Swift
Properties store or compute values on a type, while methods define the functions and behavior attached to it.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics