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.