Intern
Czym jest zbieracz śmieci (garbage collector)?
sobes.tech AI
Odpowiedź od AI
Na iOS nie ma tradycyjnego zbieracza śmieci. Zamiast niego używany jest mechanizm Automatycznego Liczenia Referencji (ARC).
- Automatyczny mechanizm: ARC automatycznie zlicza silne odwołania do obiektów.
- Zwalnianie pamięci: Gdy liczba silnych odwołań do obiektu osiąga zero, ARC zwalnia przydzieloną pamięć.
- Zapobieganie wyciekom: Poprawne użycie silnych, słabych i nieposiadanych (unowned) odwołań pozwala zapobiegać wyciekom pamięci i cyklom silnych odwołań.
Typy odwołań w ARC:
- Silne (strong): Zwiększa licznik odwołań. Domyślnie.
- Słabe (weak): Nie zwiększa licznika odwołań. Automatycznie staje się
nilpodczas deallokacji obiektu. Używane do zapobiegania cyklom silnych odwołań. Deklarowane jako typ opcjonalny. - Nieposiadane (unowned): Nie zwiększa licznika odwołań. Gwarantuje, że obiekt, na który się odwołuje, istnieje przez cały cykl życia nieposiadanego odwołania. Nie jest opcjonalne. Używane, gdy dwa obiekty mają wzajemne silne powiązanie, ale jeden z nich ma krótszy cykl życia.
Zalety ARC:
- Przewidywalność: Zwolnienie pamięci następuje deterministycznie, gdy obiekt nie jest już używany.
- Wydajność: Brak dodatkowych kosztów związanych z tłem zbieracza śmieci, które mogą powodować przerwy.
- Prostota: Programista nie musi ręcznie zarządzać pamięcią w większości przypadków, ale musi rozumieć zasady liczenia odwołań, aby zapobiec wyciekom.
Przykład cyklu silnych odwołań:
class Person {
let name: String
var apartment: Apartment? // silne odwołanie do Apartment
init(name: String) { self.name = name }
deinit { print("\(name) jest wyłączany") }
}
class Apartment {
let unit: String
weak var tenant: Person? // słabe odwołanie do Person, aby zapobiec cyklowi
init(unit: String) { self.unit = unit }
deinit { print("Mieszkanie \(unit) jest wyłączane") }
}
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john // Użycie weak tutaj jest krytyczne
john = nil
unit4A = nil
// Bez weak tenant: Zarówno john, jak i unit4A nie zostaną wyłączone.
// Z weak tenant: Zarówno john, jak i unit4A zostaną poprawnie wyłączone.