Unowned Reference is a non-owning reference in Swift that does not increase the object’s retain count and, unlike weak, is not set to nil after the object is deallocated. According to Apple Swift Language Guide, 2026, unowned is used when it is guaranteed that the object lives at least as long as the object referencing it. Unlike Weak Reference, unowned does not require unwrap — it is a non-optional type, which makes code cleaner but places responsibility on the developer to guarantee the lifetime.
Key Takeaways
Unowned Reference is a non-owning reference to an object in ARC that does not increase its retain count. Unlike weak, an unowned reference is not zeroed after the object is deallocated: it continues to point to memory that has already been freed. Accessing such a reference causes a runtime crash with EXC_BAD_ACCESS.
The term “unowned” reflects the semantics: the object exists, but no one is responsible for its lifetime. The developer explicitly states: “I guarantee this object will be alive as long as I reference it.” The compiler does not verify this guarantee — it is a contract at the developer level.
According to Swift.org Documentation, 2026, unowned references are preferred over weak in scenarios with guaranteed lifetime because they: do not require an optional type (cleaner code), do not require unwrap (less force-unwrap or guard let), and have no overhead from maintaining a zeroing weak table. However, any breach of the contract results in a crash.
In Swift, unowned references are declared with the keyword unowned before let or var. Unlike weak, unowned can be both let and var, and does not require an optional type. This property makes unowned convenient for references that cannot be nil by domain logic.
class Country {
let name: String
var capital: City! // will be set after initialization
init(name: String) { self.name = name }
}
class City {
let name: String
unowned let country: Country // ✅ unowned let — lifetime guarantee
init(name: String, country: Country) {
self.name = name
self.country = country
}
}
// Usage
let france = Country(name: "France")
let paris = City(name: "Paris", country: france)
france.capital = paris
// ✅ Country → City (strong), City → Country (unowned) — no retain cycle
In this example, City unowned let country — a city cannot exist without a country. If the country disappears, the city (and the reference) lose their meaning. Semantically, this is an ideal case for unowned: lifetime guarantee exists, optional is not needed, retain cycle does not occur.
unowned var is allowed but less common. It is used when the reference may be replaced (e.g., reassigning a child to a different parent). Upon reassignment, the deallocation of the old object is the responsibility of the external owner.
In Swift 5.0+, support for unowned optional (unowned let x: Type?) was introduced. This is a compromise: unowned guarantees that if the reference is not nil, the object is alive. Behavior upon deallocation is a crash, same as with regular unowned.
The choice between unowned and weak is one of the frequent decisions when designing Swift architecture. Let’s examine the criteria and recommendations for each case.
| Criterion | Weak | Unowned |
|---|---|---|
| Optional | Yes (Type?) | No (Type) |
| Zeroing on deallocation | Auto to nil | No (dangling pointer risk) |
| Type (let/var) | var only | let or var |
| Performance | Overhead from weak table | Minimal (simple pointer) |
| Safety | Safe (nil checked) | Risk of EXC_BAD_ACCESS |
| Lifetime guarantee | Not required | Explicit guarantee required |
Use weak if there is even the slightest doubt about the object’s lifetime. Weak is safe, clear, and requires no proof. Use unowned only when you can rule out all scenarios in which the object could be deallocated earlier. Typical cases: a child that does not exist without a parent; a closure that executes synchronously; accessing an object within its initializer.
According to Airbnb Swift Style Guide, 2025, in large codebases it is recommended to use weak by default and unowned only with an explicit comment explaining the lifetime guarantee. This reduces the risk of non-obvious crashes during refactoring.
Closures are the second most frequent use case for unowned after parent-child relationships. The capture list [unowned self] is used when self is guaranteed to outlive the closure. Let’s examine correct and incorrect scenarios.
Synchronous closures — sorted, filter, map. They execute immediately on the current thread, self is definitely alive. A capture list with unowned is acceptable here and results in cleaner code.
class DataProcessor {
var items: [Int] = [3, 1, 4, 1, 5]
func processSorted() {
// ✅ unowned self — sorted executes synchronously, self is guaranteed alive
let sorted = items.sorted { [unowned self] a, b in
return self.customCompare(a, b)
}
}
func customCompare(_ a: Int, _ b: Int) -> Bool { return a < b }
}
Asynchronous closures — with delays, network requests, animations. Self may be deallocated between scheduling the closure and its execution. Here unowned self leads to a crash. Use [weak self].
class NetworkLoader {
func loadData() {
// ❌ DANGEROUS: unowned self in async closure
URLSession.shared.dataTask(with: url) { [unowned self] data, _, _ in
self.handleResponse(data) // CRASH if self is deallocated
}.resume()
}
func handleResponse(_ data: Data?) { }
// ✅ CORRECT: weak self + guard
func loadDataSafe() {
URLSession.shared.dataTask(with: url) { [weak self] data, _, _ in
guard let self else { return }
self.handleResponse(data)
}.resume()
}
}
Remember the rule: unowned self — only for synchronous closures that execute immediately. For asynchronous closures, always use weak self + guard let. Exception: if you explicitly hold a reference to the object until the closure completes (e.g., by keeping a strong reference in another variable).
Unowned is a powerful but dangerous tool. Let’s examine real-world scenarios where unowned can lead to crashes and methods for minimizing risk.
The main risk of unowned is a change in business logic that invalidates the lifetime guarantee. A developer refactors the code: changes ownership, introduces deferred deallocation, adds caching — and the unowned reference becomes a time bomb. The compiler will not warn you — only a crash on the user’s device.
Recommendation: use unowned only when the lifetime guarantee is obvious and documented. Add a comment to each unowned: why this reference is safe and under what conditions it could be violated.
UIKit is a high-risk area for unowned. A ViewController can be deallocated at any moment during navigation (pop, dismiss), memory unloading, or orientation changes. If you pass a ViewController into a closure with unowned self, self may be nil when returning from the background or upon animation completion.
To reduce the risk when using unowned, follow these rules:
// Example: documented unowned reference with explicit justification
class InvoiceLineItem {
let productName: String
let price: Decimal
// unowned Invoice — InvoiceLineItem cannot exist without Invoice.
// Invoice creates Item and removes it when it is deleted.
// Guarantee: Invoice lives at least as long as Item.
unowned let invoice: Invoice
init(productName: String, price: Decimal, invoice: Invoice) {
self.productName = productName
self.price = price
self.invoice = invoice
}
}
// This is a strong guarantee: Invoice removes all Items in deinit.
// violating the guarantee = a bug in business logic that needs to be fixed.
Documenting guarantees is a professional standard. In large projects (Airbnb, Uber), code review requires justification for every unowned. If the guarantee is not obvious, use weak. A comment on unowned helps future developers understand why weak was not used here and what conditions could break the guarantee.
Frequently Asked Questions
Runtime crash with EXC_BAD_ACCESS. Swift does not check the validity of an unowned reference on access — it is simply a “raw” pointer. If the object is deallocated, the memory is overwritten, and accessing it terminates fatally. This is a non-catchable exception (not try-catch).
Yes, if the protocol inherits from AnyObject. Unowned works with all reference types: classes, AnyObject protocols, Objective-C objects. Value types (struct, enum) do not support unowned because they do not participate in ARC.
When the lifetime guarantee is absolute and obvious — unowned is safer from a design perspective: it does not require unwrap, cannot be nil, and does not mask errors. If an object cannot exist without a parent, unowned makes this an explicit contract, while weak blurs the guarantee.
Yes: unowned is faster because it does not require access to the runtime weak table for zeroing. In most applications the difference is imperceptible, but in high-load scenarios with millions of accesses, unowned can be 10–20% faster on reads.
Refactoring is the main danger for unowned. Changing the object’s lifetime (caching, asynchronous operations, reuse) can break the guarantee. The compiler will not warn you. Solution: migrate to weak when changing architecture or add a warning comment.
Summary
unowned let or unowned var; can be non-optional and optional (Swift 5.0+)We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also