Sobes.tech
Junior

Jak działa zbieracz śmieci?

sobes.tech AI

Odpowiedź od AI

W kontekście rozwoju iOS/macOS, Swift/Objective-C nie używa zbieracza śmieci (GC), lecz automatycznego zliczania odwołań (Automatic Reference Counting, ARC).

ARC automatycznie zarządza pamięcią, zliczając liczbę silnych odwołań do każdej instancji klasy (oraz zamknięć z przechwytem). Gdy licznik silnych odwołań osiąga zero, system zwalnia pamięć zajmowaną przez obiekt.

Kluczowe punkty ARC:

  • Silne odwołania (Strong): Zwiększają licznik odwołań. Obiekt pozostaje w pamięci, dopóki ma co najmniej jedno silne odwołanie.
  • Słabe odwołania (Weak): Nie zwiększają licznika odwołań. Używane są do unikania cykli silnych odwołań. Odwołują się opcjonalnie do obiektu, który staje się nil, gdy obiekt zostanie zwolniony.
  • Nieposiadane odwołania (Unowned): Nie zwiększają licznika odwołań. Używane, gdy znany jest cykl życia obiektów i jeden obiekt zawsze będzie istniał, dopóki inny istnieje. Odwołanie nie jest opcjonalne. Jeśli obiekt, na który się odwołuje unowned, zostanie zwolniony, dostęp do niego spowoduje błąd w czasie wykonywania.

ARC działa na etapie kompilacji, wstawiając wywołania retain (zwiększenie licznika) i release (zmniejszenie licznika) w odpowiednim kodzie.

class MyClass {  
    var prop: String = ""  
}

var reference1: MyClass? = MyClass() // Licznik = 1
var reference2 = reference1 // Licznik = 2

reference1 = nil // Licznik = 1
reference2 = nil // Licznik = 0, obiekt jest zwalniany
class Person {  
    let name: String
    weak var apartment: Apartment? // Słabe odwołanie, aby uniknąć cyklu
    init(name: String) { self.name = name; print("\(name) jest inicjalizowany") }
    deinit { print("\(name) jest deinitializowany") }
}

class Apartment {  
    let unit: String
    unowned var tenant: Person // Nieposiadane odwołanie
    init(unit: String, tenant: Person) { self.unit = unit; self.tenant = tenant; print("Mieszkanie \(unit) jest inicjalizowane") }
    deinit { print("Mieszkanie \(unit) jest deinitializowane") }
}