Sobes.tech
Middle

What is automatic link counting?

sobes.tech AI

Answer from AI

Automatic Reference Counting (ARC) is a memory management mechanism in Swift and Objective-C that automatically tracks and releases memory allocated for objects. Each class instance has a reference count that increases when a strong reference to the object is created and decreases when it is removed. When the reference count reaches zero, ARC automatically deallocates the object and frees the memory it occupied.

ARC prevents memory leaks and double freeing, simplifying memory management compared to manual management (as in Objective-C without ARC).

There are three types of references:

  1. Strong: Increases the reference count of the object. It is the default reference type.
  2. Weak: Does not increase the reference count. Used to prevent strong reference cycles when two objects strongly reference each other. A weak reference becomes nil if the object it points to is deallocated. Defined with the weak keyword.
  3. Unowned: Does not increase the reference count and always has a value. Used when it is known that the reference will always point to an object as long as the object exists. Unlike weak, an unowned reference does not become nil and can cause a crash if accessed after the object is deallocated. Defined with the unowned keyword.

Example of a strong reference cycle:

class Human {
    let name: String
    var apartment: Apartment? // Strong reference to optional Apartment
    init(name: String) {
        self.name = name
        print("\(name) is being initialized")
    }
    deinit {
        print("\(name) is being deinitialized")
    }
}

class Apartment {
    let unit: String
    var tenant: Human? // Strong reference to optional Human
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) is being initialized")
    }
    deinit {
        print("Apartment \(unit) is being deinitialized")
    }
}

var john: Human?
var unit4A: Apartment?

john = Human(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

john = nil
unit4A = nil
// Neither "John Appleseed is being deinitialized" nor "Apartment 4A is being deinitialized" will be printed due to the strong reference cycle

Solution to the strong reference cycle using weak:

class Human {
    let name: String
    var apartment: Apartment?
    init(name: String) {
        self.name = name
        print("\(name) is being initialized")
    }
    deinit {
        print("\(name) is being deinitialized")
    }
}

class Apartment {
    let unit: String
    weak var tenant: Human? // Weak reference
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) is being initialized")
    }
    deinit {
        print("Apartment \(unit) is being deinitialized")
    }
}

var john: Human?
var unit4A: Apartment?

john = Human(name: "John Appleseed")
unit4A = Apartment(unit: "4A")

john!.apartment = unit4A
unit4A!.tenant = john

john = nil // John is deallocated as its reference count becomes 0
unit4A = nil // Apartment is deallocated as its reference count becomes 0
What is automatic link counting? — iOS - sobes.tech