Sobes.tech
Middle

Ποια είναι η διαφορά μεταξύ των συνδέσμων Wick και των συνδέσμων Anound;

sobes.tech AI

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

Ο ασθενής αναφορά (weak) είναι μια αναφορά που δεν αυξάνει τον μετρητή αναφορών του αντικειμένου. Χρησιμοποιείται για την αποτροπή κύκλων ισχυρών αναφορών, για παράδειγμα, μεταξύ ενός διαμεσολαβητή και του ιδιοκτήτη του. Αν το αντικείμενο στο οποίο δείχνει η ασθενής αναφορά διαγραφεί, η ασθενής αναφορά γίνεται αυτόματα nil.

Η αναφορά χωρίς ιδιοκτησία (unowned) είναι επίσης μια αναφορά που δεν αυξάνει τον μετρητή αναφορών του αντικειμένου. Η διαφορά με το weak είναι ότι το unowned δεν μπορεί να είναι προαιρετικό (Optional) και πρέπει πάντα να δείχνει σε ένα υπάρχον αντικείμενο. Αν το αντικείμενο στο οποίο δείχνει η unowned αναφορά διαγραφεί πριν από την πρόσβαση σε αυτή, θα προκληθεί σφάλμα εκτέλεσης (fatal error). Χρησιμοποιείται εκεί όπου ο κύκλος ζωής του σχετιζόμενου αντικειμένου είναι εγγυημένο ότι είναι μεγαλύτερος ή ίσος με τον κύκλο ζωής του αντικειμένου με την unowned αναφορά (για παράδειγμα, σε κύκλο ισχυρών αναφορών όπου ένα από τα αντικείμενα έχει σαφώς ορισμένο κύκλο ζωής).

Σύγκριση:

Χαρακτηριστικό weak unowned
Μη ιδιοκτήτης Ναι Ναι
Αυξάνει το SC Όχι Όχι
Μπορεί να είναι nil Ναι (αυτόματα μηδενίζεται) Όχι (πρέπει πάντα να δείχνει σε αντικείμενο)
Ασφάλεια Πιο ασφαλές σε περίπτωση διαγραφής Λιγότερο ασφαλές (fatal σφάλμα κατά την πρόσβαση σε διαγραμμένο αντικείμενο)
Τύπος Πρέπει να είναι προαιρετικό Δεν μπορεί να είναι προαιρετικό (προεπιλογή)
Χρήση Πρόληψη κύκλων ισχυρών αναφορών, όπου το αντικείμενο μπορεί να σταματήσει να υφίσταται νωρίτερα Πρόληψη κύκλων ισχυρών αναφορών, όπου το αντικείμενο εγγυάται την ύπαρξή του

Παράδειγμα χρήσης weak για την αποτροπή κύκλου ισχυρών αναφορών:

class Person {
    let name: String
    weak var apartment: Apartment? // ασθενής αναφορά για αποφυγή κύκλου

    init(name: String) {
        self.name = name
        print("\(name) αρχικοποιείται")
    }

    deinit {
        print("\(name) αφαιρείται")
    }
}

class Apartment {
    let unit: String
    var occupant: Person?

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

    deinit {
        print("Διαμέρισμα \(unit) αφαιρείται")
    }
}

Παράδειγμα χρήσης unowned στο πλαίσιο της καταγραφής του self σε κλείσιμο:

class HTMLElement {
    let name: String
    let text: String?

    lazy var asHTML: () -> String = {
        [unowned self] in // unowned self για αποφυγή κύκλου
        if let text = self.text {
            return "<\(self.name)>\(text)</\(self.name)>"
        } else {
            return "<\(self.name) />"
        }
    }

    init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
    }

    deinit {
        print("\(name) αφαιρείται")
    }
}