Sobes.tech
Middle

What types of references exist in Swift?

sobes.tech AI

Answer from AI

In Swift, there are three main types of references:

  1. Strong Reference:

    • Increases the reference count of an object instance.
    • Prevents deallocation of the object as long as at least one strong reference exists.
    • Is the default reference type in Swift.
    • The main cause of strong reference cycles.
  2. Weak Reference:

    • Does not increase the reference count.
    • Allows deallocation of the object if there are no more strong references.
    • Declared using the weak keyword.
    • Always an optional (Optional) because the referenced object can be nil.
    • Used to prevent strong reference cycles, especially when one instance can exist independently of another.
    class Person {
        let name: String
        weak var apartment: Apartment? // Weak reference
        init(name: String) {
            self.name = name
        }
        deinit { print("\(name) deallocated") }
    }
    
    class Apartment {
        let unit: String
        var tenant: Person? // Regular strong reference
        init(unit: String) {
            self.unit = unit
        }
        deinit { print("Apartment \(unit) deallocated") }
    }
    
    var john: Person?
    var unit4A: Apartment?
    
    john = Person(name: "John Appleseed")
    unit4A = Apartment(unit: "4A")
    
    john!.apartment = unit4A
    unit4A!.tenant = john // Without weak, this would create a strong reference cycle
    
    // References are nulled, objects are deallocated
    john = nil
    unit4A = nil
    
  3. Unowned Reference:

    • Does not increase the reference count.
    • Allows deallocation if there are no more strong references.
    • Declared using the unowned keyword.
    • Not an optional. It is assumed that the referenced object will always exist as long as the instance with the unowned reference exists.
    • Accessing an unowned reference after the object has been deallocated will cause a runtime crash.
    • Used to prevent strong reference cycles when one instance should always exist as long as another does, and it is not possible for the reference to become nil (e.g., self in closures).
    class Customer {
        let name: String
        var card: CreditCard?
        init(name: String) {
            self.name = name
        }
        deinit { print("\(name) deallocated") }
    }
    
    class CreditCard {
        let number: UInt64
        unowned let customer: Customer // Unowned reference
        init(number: UInt64, customer: Customer) {
            self.number = number
            self.customer = customer
        }
        deinit { print("Card #\(number) deallocated") }
    }
    
    var john: Customer? = Customer(name: "John Appleseed")
    john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    
    // If the customer is set to nil, the card referencing it with unowned will become invalid,
    // but it will not cause a cycle.
    john = nil // Both objects are deallocated
    

The choice between weak and unowned depends on the nature of the relationship between objects: use weak when one object may exist without the other (Person without Apartment), and unowned when one object must always exist as long as the other (CreditCard always belongs to a Customer).

What types of references exist in Swift? — iOS - sobes.tech