Sobes.tech
Intern

Τι είναι ο συλλέκτης απορριμμάτων (garbage collector);

sobes.tech AI

Απάντηση από AI

Στο iOS, δεν υπάρχει παραδοσιακός συλλέκτης απορριμμάτων. Αντ' αυτού, χρησιμοποιείται ο μηχανισμός Αυτόματης Αναφοράς (ARC).

  • Αυτόματος μηχανισμός: Το ARC μετρά αυτόματα τις ισχυρές αναφορές στα αντικείμενα.
  • Απελευθέρωση μνήμης: Όταν ο αριθμός των ισχυρών αναφορών σε ένα αντικείμενο φτάσει το μηδέν, το ARC απελευθερώνει τη δεσμευμένη μνήμη.
  • Πρόληψη διαρροών μνήμης: Η σωστή χρήση ισχυρών, αδύναμων και μη κατόχων (unowned) αναφορών επιτρέπει την πρόληψη διαρροών μνήμης και κύκλων ισχυρών αναφορών.

Τύποι αναφορών στο ARC:

  • Ισχυρή (strong): Αυξάνει τον μετρητή αναφορών. Είναι η προεπιλογή.
  • Αδύναμη (weak): Δεν αυξάνει τον μετρητή αναφορών. Γίνεται αυτόματα nil κατά την αποδέσμευση του αντικειμένου. Χρησιμοποιείται για την πρόληψη κύκλων ισχυρών αναφορών. Δηλώνεται ως προαιρετικός τύπος.
  • Μη κατόχος (unowned): Δεν αυξάνει τον μετρητή αναφορών. Διασφαλίζεται ότι το αντικείμενο στο οποίο αναφέρεται υπάρχει καθ' όλη τη διάρκεια ζωής της μη κατόχου αναφοράς. Δεν είναι προαιρετικό. Χρησιμοποιείται όταν δύο αντικείμενα έχουν αμοιβαία ισχυρή σχέση, αλλά ένα από αυτά έχει μικρότερη διάρκεια ζωής.

Πλεονεκτήματα του ARC:

  • Προβλεψιμότητα: Η απελευθέρωση μνήμης συμβαίνει deterministically, μόλις το αντικείμενο δεν χρησιμοποιείται πλέον.
  • Απόδοση: Δεν υπάρχουν πρόσθετα έξοδα για τον συλλέκτη απορριμμάτων στο παρασκήνιο, που μπορεί να προκαλέσουν διακοπές.
  • Απλότητα: Ο προγραμματιστής δεν χρειάζεται να διαχειρίζεται χειροκίνητα τη μνήμη στις περισσότερες περιπτώσεις, αλλά πρέπει να κατανοεί τις αρχές της καταμέτρησης αναφορών για την πρόληψη διαρροών.

Παράδειγμα κύκλου ισχυρών αναφορών:

class Person {
    let name: String
    var apartment: Apartment? // ισχυρή αναφορά σε Apartment

    init(name: String) { self.name = name }
    deinit { print("\(name) αποδεσμεύεται") }
}

class Apartment {
    let unit: String
    weak var tenant: Person? // αδύναμη αναφορά σε Person για την πρόληψη κύκλου

    init(unit: String) { self.unit = unit }
    deinit { print("Διαμέρισμα \(unit) αποδεσμεύεται") }
}

var john: Person?
var unit4A: Apartment?

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

john!.apartment = unit4A
unit4A!.tenant = john // Η χρήση του weak εδώ είναι κρίσιμη

john = nil
unit4A = nil
// Χωρίς weak tenant: Τόσο ο john όσο και το unit4A δεν θα αποδεσμευτούν.
// Με weak tenant: Τόσο ο john όσο και το unit4A αποδεσμεύονται σωστά.