Sobes.tech
Middle

What is the difference between 'weak' and 'unowned' in Swift?

sobes.tech AI

Answer from AI

weak and unowned are used to resolve cyclic references but differ in their behavior and application.

Property 'weak' 'unowned'
Type Optional Non-optional
Lifetime Can become nil Guaranteed to have a value
Existence guarantee No Yes, until the end of Scope
Usage When it is possible that the related object will be deallocated first. When the related object will be deallocated either simultaneously with or after the current one.
Example Delegate Parent-Child relationship

weak:

  • Used when one object can exist without a reference to another, or when one of the objects is allowed to be nil.
  • Automatically becomes nil when the object it references is deallocated.
  • Must be declared as an optional type.
class Person {
    let name: String
    var apartment: Apartment?

    init(name: String) { self.name = name }
    deinit { print("\(name) is being deinitialized") }
}

class Apartment {
    let unit: String
    weak var tenant: Person? // cyclic reference solved with weak

    init(unit: String) { self.unit = unit }
    deinit { print("Apartment \(unit) is being deinitialized") }
}

var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")

john?.apartment = unit4A
unit4A?.tenant = john // No strong reference cycle

john = nil // Person object is deallocated
// unit4A?.tenant is now nil

unit4A = nil // Apartment object is deallocated

unowned:

  • Used when one object belongs to another, and both should exist simultaneously or the related object will outlive the current one.
  • Guaranteed to always have a value. Accessing it after deallocation will cause a runtime error.
  • Declared as a non-optional type.
class Customer {
    let name: String
    var card: CreditCard?

    init(name: String) { self.name = name }
    deinit { print("\(name) is being deinitialized") }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer // cyclic reference solved with unowned

    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }
    deinit { print("Card #\(number) is being deinitialized") }
}

var john: Customer? = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!) // No strong reference cycle

john = nil // Customer and CreditCard objects are deallocated

The choice between weak and unowned depends on whether the related object can become nil during the lifetime of the current object. If yes, use weak. If not, use unowned.

What is the difference between 'weak' and 'unowned'… - sobes.tech