Sobes.tech
Middle

Τι είναι το unowned στη γλώσσα Swift και πώς χρησιμοποιείται;

sobes.tech AI

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

Η μη κατέχουσα αναφορά (αδύναμη έμμεση ιδιοκτησία) στο Swift χρησιμοποιείται για την αποφυγή κύκλων ισχυρής ιδιοκτησίας (retain cycles), όταν δύο αντικείμενα αναφέρονται το ένα στο άλλο με ισχυρό τρόπο, εμποδίζοντας την απελευθέρωσή τους από τη μνήμη.

Χαρακτηριστικά του unowned:

  • Διασφαλίζει ότι το αντικείμενο στο οποίο αναφέρεται η unowned αναφορά υπάρχει πάντα μέχρι τη στιγμή που χρησιμοποιείται.
  • Αν προσπαθήσετε να αποκτήσετε πρόσβαση στην unowned αναφορά μετά την απελευθέρωση του σχετικού αντικειμένου, θα προκληθεί σφάλμα κατά την εκτέλεση (runtime crash).
  • Χρησιμοποιείται όταν ο κύκλος ζωής του αντικειμένου που αναφέρεται δεν είναι μεγαλύτερος από αυτό του αντικειμένου που αναφέρεται. Με άλλα λόγια, η unowned αναφορά δεν καθιστά το αντικείμενο ισχυρό.

Παράδειγμα χρήσης σε σύλληψη κλεισίματος:

class Customer {
    let name: String
    var card: CreditCard?

    init(name: String) {
        self.name = name
    }

    deinit {
        print("\(name) απελευθερώνεται")
    }
}

class CreditCard {
    let number: UInt64
    unowned let customer: Customer // Μη κατέχουσα αναφορά σε Customer

    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }

    deinit {
        print("Κάρτα #\(number) απελευθερώνεται")
    }
}

var john: Customer? // Προαιρετικός Customer για απελευθέρωση
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

// Ανάθεση nil στον john θα οδηγήσει στην απελευθέρωση του Customer και της Card,
// καθώς δεν υπάρχει κύκλος ισχυρής ιδιοκτησίας
john = nil 

Άλλο παράδειγμα - χρήση του unowned σε λίστα σύλληψης κλεισίματος:

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) απελευθερώνεται")
    }
}

var paragraph: HTMLElement? // Προαιρετικό στοιχείο HTML
paragraph = HTMLElement(name: "p", text: "γεια σου κόσμε")
print(paragraph!.asHTML())

// Ανάθεση nil θα απελευθερώσει το HTMLElement, καθώς η κλεισίματος δεν το κρατάει ισχυρά
paragraph = nil

Η επιλογή μεταξύ unowned και weak εξαρτάται από το αν η αναφορά μπορεί να γίνει nil κατά τη διάρκεια ζωής του αντικειμένου. Αν η αναφορά ποτέ δεν μπορεί να γίνει nil πριν από την απελευθέρωση του αντικειμένου, χρησιμοποιήστε unowned. Αν μπορεί, χρησιμοποιήστε weak.