Sobes.tech
Intern

Was ist ein Garbage Collector (Müllsammler)?

sobes.tech KI

Antwort von AI

Auf iOS gibt es keinen herkömmlichen Müllsammler. Stattdessen wird der Mechanismus der Automatischen Referenzzählung (ARC) verwendet.

  • Automatischer Mechanismus: ARC zählt automatisch die starken Referenzen auf Objekte.
  • Speicherfreigabe: Wenn die Anzahl der starken Referenzen auf ein Objekt null erreicht, gibt ARC den zugewiesenen Speicher frei.
  • Vermeidung von Speicherlecks: Die korrekte Verwendung von starken, schwachen und unbesessenen (unowned) Referenzen ermöglicht die Vermeidung von Speicherlecks und Zyklen in Referenzen.

Referenztypen in ARC:

  • Stark (strong): Erhöht den Referenzzähler. Standardmäßig.
  • Schwach (weak): Erhöht den Referenzzähler nicht. Wird automatisch nil, wenn das Objekt deallokiert wird. Wird verwendet, um Zyklen in starken Referenzen zu vermeiden. Wird als optionaler Typ deklariert.
  • Unbesessen (unowned): Erhöht den Referenzzähler nicht. Es wird garantiert, dass das referenzierte Objekt während des gesamten Lebenszyklus der unbesessenen Referenz existiert. Ist nicht optional. Wird verwendet, wenn zwei Objekte eine gegenseitige starke Beziehung haben, aber eines einen kürzeren Lebenszyklus hat.

Vorteile von ARC:

  • Vorhersagbarkeit: Die Speicherfreigabe erfolgt deterministisch, sobald das Objekt nicht mehr verwendet wird.
  • Leistung: Es gibt keine zusätzlichen Hintergrundkosten durch einen Müllsammler, der Pausen verursachen könnte.
  • Einfachheit: Der Entwickler muss die Speicherverwaltung in den meisten Fällen nicht manuell durchführen, sollte aber die Prinzipien der Referenzzählung verstehen, um Lecks zu vermeiden.

Beispiel für einen Zyklus starker Referenzen:

class Person {
    let name: String
    var apartment: Apartment? // starke Referenz auf Apartment

    init(name: String) { self.name = name }
    deinit { print("\(name) wird deinitialisiert") }
}

class Apartment {
    let unit: String
    weak var tenant: Person? // schwache Referenz auf Person, um Zyklen zu vermeiden

    init(unit: String) { self.unit = unit }
    deinit { print("Apartment \(unit) wird deinitialisiert") }
}

var john: Person?
var unit4A: Apartment?

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

john!.apartment = unit4A
unit4A!.tenant = john // Die Verwendung von weak ist hier kritisch

john = nil
unit4A = nil
// Ohne weak tenant: Sowohl john als auch unit4A würden nicht deinitialisiert.
// Mit weak tenant: Sowohl john als auch unit4A werden korrekt deinitialisiert.