Τι είναι η αυτόματη καταμέτρηση συνδέσμων;
sobes.tech AI
Απάντηση από AI
Ο αυτόματος υπολογισμός αναφορών (Automatic Reference Counting, ARC) είναι ένας μηχανισμός διαχείρισης μνήμης στα Swift και Objective-C, ο οποίος παρακολουθεί και απελευθερώνει αυτόματα τη μνήμη που έχει εκχωρηθεί για αντικείμενα. Κάθε αντικείμενο κλάσης έχει έναν μετρητή αναφορών, ο οποίος αυξάνεται κατά τη δημιουργία μιας ισχυρής αναφοράς σε αυτό και μειώνεται κατά την διαγραφή της. Όταν ο μετρητής αναφορών φτάσει το μηδέν, το ARC αυτόματα απελευθερώνει το αντικείμενο και τη μνήμη που καταλαμβάνει.
Το ARC αποτρέπει διαρροές μνήμης και διπλή απελευθέρωση, απλοποιώντας τη διαχείριση μνήμης σε σύγκριση με την χειροκίνητη διαχείριση (όπως στο Objective-C χωρίς ARC).
Υπάρχουν τρεις τύποι αναφορών:
- Strong (Ισχυρή): Αυξάνει τον μετρητή αναφορών του αντικειμένου. Είναι ο προεπιλεγμένος τύπος αναφοράς.
- Weak (Αδύναμη): Δεν αυξάνει τον μετρητή αναφορών. Χρησιμοποιείται για την αποτροπή κύκλων ισχυρών αναφορών, όταν δύο αντικείμενα αναφέρονται το ένα στο άλλο. Μια αδύναμη αναφορά γίνεται
nilαν το αντικείμενο στο οποίο αναφέρεται διαγραφεί. Ορίζεται με τη λέξη-κλειδίweak. - Unowned (Ανεξάρτητη): Δεν αυξάνει τον μετρητή αναφορών και πάντα έχει μια τιμή. Χρησιμοποιείται όταν είναι γνωστό ότι η αναφορά θα δείχνει πάντα σε ένα αντικείμενο όσο αυτό υπάρχει. Σε αντίθεση με το
weak, η ανεξάρτητη αναφορά δεν γίνεταιnilκαι μπορεί να προκαλέσει σφάλμα αν προσπαθήσετε να αποκτήσετε πρόσβαση σε αντικείμενο μετά τη διαγραφή του. Ορίζεται με τη λέξη-κλειδίunowned.
Παράδειγμα κύκλου ισχυρών αναφορών:
class Human {
let name: String
var apartment: Apartment? // Ισχυρή αναφορά σε προαιρετικό Apartment
init(name: String) {
self.name = name
print("\(name) is being initialized")
}
deinit {
print("\(name) is being deinitialized")
}
}
class Apartment {
let unit: String
var tenant: Human? // Ισχυρή αναφορά σε προαιρετικό Human
init(unit: String) {
self.unit = unit
print("Apartment \(unit) is being initialized")
}
deinit {
print("Apartment \(unit) is being deinitialized")
}
}
var john: Human?
var unit4A: Apartment?
john = Human(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil
unit4A = nil
// Ούτε "John Appleseed is being deinitialized" ούτε "Apartment 4A is being deinitialized" θα εμφανιστούν λόγω του κύκλου ισχυρών αναφορών
Λύση του προβλήματος κύκλου ισχυρών αναφορών με χρήση του weak:
class Human {
let name: String
var apartment: Apartment?
init(name: String) {
self.name = name
print("\(name) is being initialized")
}
deinit {
print("\(name) is being deinitialized")
}
}
class Apartment {
let unit: String
weak var tenant: Human? // Αδύναμη αναφορά
init(unit: String) {
self.unit = unit
print("Apartment \(unit) is being initialized")
}
deinit {
print("Apartment \(unit) is being deinitialized")
}
}
var john: Human?
var unit4A: Apartment?
john = Human(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john
john = nil // Ο John διαγράφεται, καθώς ο μετρητής αναφορών του γίνεται 0
unit4A = nil // Το διαμέρισμα διαγράφεται, καθώς ο μετρητής αναφορών του γίνεται 0