Unowned Reference: τι είναι, σύνταξη και εφαρμογή σε κινητές εφαρμογές

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-03-30 Χρόνος ανάγνωσης: 9 λεπ

Unowned Reference (αναφορά χωρίς κάτοχο) — είναι μια μη κατέχουσα αναφορά στη Swift που δεν αυξάνει το retain count του αντικειμένου και, σε αντίθεση με το weak, δεν ορίζεται σε nil μετά την απελευθέρωσή του. Σύμφωνα με το Apple Swift Language Guide, 2026, το unowned εφαρμόζεται όταν είναι εγγυημένο ότι το αντικείμενο ζει τουλάχιστον όσο το αντικείμενο που αναφέρεται σε αυτό. Σε αντίθεση με το Weak Reference, το unowned δεν απαιτεί unwrap — είναι τύπος non-optional, που κάνει τον κώδικα καθαρότερο, αλλά θέτει την ευθύνη της εγγύησης ζωής στον προγραμματιστή.

Κύρια Σημεία

  • Unowned Reference — μη κατέχουσα αναφορά χωρίς αυτόματο μηδενισμό· non-optional, δεν αυξάνει το retain count
  • Εγγύηση — εφαρμόζεται όταν το αντικείμενο είναι εγγυημένο ότι δεν μπορεί να απελευθερωθεί πριν από το αντικείμενο που αναφέρεται σε αυτό
  • Διαφορά από weak — το unowned δεν μηδενίζεται σε nil (ρίσκο crash), το weak μηδενίζεται (ασφαλές)
  • Σενάρια — parent-child με εγγύηση ζωής, closures με unowned self, singletons και Service Locator
  • Ρίσκο — η πρόσβαση σε ένα απελευθερωμένο unowned αντικείμενο προκαλεί runtime crash (EXC_BAD_ACCESS)

Τι είναι το Unowned Reference;

Unowned Reference — είναι μια μη κατέχουσα αναφορά σε ένα αντικείμενο στο ARC που δεν αυξάνει το retain count του. Σε αντίθεση με το weak, το unowned δεν μηδενίζεται μετά την αποδέσμευση του αντικειμένου: συνεχίζει να δείχνει στην περιοχή μνήμης που έχει ήδη απελευθερωθεί. Η πρόσβαση σε μια τέτοια αναφορά προκαλεί runtime crash με EXC_BAD_ACCESS.

Ο όρος "χωρίς κάτοχο" αντικατοπτρίζει τη σημασιολογία: το αντικείμενο υπάρχει, αλλά κανείς δεν ευθύνεται για τη διάρκεια ζωής του. Ο προγραμματιστής δηλώνει ρητά: "εγγυώμαι ότι αυτό το αντικείμενο θα ζει όσο αναφέρομαι σε αυτό". Ο μεταγλωττιστής δεν ελέγχει αυτήν την εγγύηση — είναι ένα συμβόλαιο σε επίπεδο προγραμματιστή.

Σύμφωνα με το Swift.org Documentation, 2026, οι unowned αναφορές προτιμώνται έναντι των weak σε σενάρια με εγγυημένη διάρκεια ζωής επειδή: δεν απαιτούν προαιρετικό τύπο (καθαρότερος κώδικας), δεν απαιτούν unwrap (λιγότερο force-unwrap ή guard let) και δεν έχουν επιβάρυνση για τη διατήρηση του πίνακα zeroing weak. Ωστόσο, οποιαδήποτε παραβίαση του συμβολαίου — crash.

Σύνταξη του unowned στη Swift

Στη Swift, οι unowned αναφορές δηλώνονται με τη λέξη-κλειδί unowned πριν από let ή var. Σε αντίθεση με το weak, το unowned μπορεί να είναι τόσο let όσο και var και δεν απαιτεί προαιρετικό τύπο. Αυτή η ιδιότητα καθιστά το unowned βολικό για αναφορές που δεν μπορούν να είναι nil σύμφωνα με τη λογική του τομέα.

swift
class Country {
    let name: String
    var capital: City!           // θα οριστεί μετά την αρχικοποίηση
    init(name: String) { self.name = name }
}

class City {
    let name: String
    unowned let country: Country   // unowned let — εγγύηση ζωής

    init(name: String, country: Country) {
        self.name = name
        self.country = country
    }
}

// Χρήση
let france = Country(name: "France")
let paris = City(name: "Paris", country: france)
france.capital = paris
// Country → City (strong), City → Country (unowned) — χωρίς retain cycle

Σε αυτό το παράδειγμα City unowned let country — η πόλη δεν μπορεί να υπάρξει χωρίς χώρα. Αν η χώρα εξαφανιστεί, η πόλη (και η αναφορά) χάνουν το νόημά τους. Σημασιολογικά, αυτή είναι ιδανική περίπτωση για unowned: εγγύηση διάρκειας ζωής υπάρχει, optional δεν χρειάζεται, retain cycle δεν δημιουργείται.

unowned var

Το unowned var επιτρέπεται αλλά εμφανίζεται σπανιότερα. Χρησιμοποιείται όταν η αναφορά μπορεί να αντικατασταθεί (π.χ. επανασύνδεση ενός παιδιού σε διαφορετικό γονέα). Κατά την αντικατάσταση, η απελευθέρωση του παλιού αντικειμένου είναι ευθύνη του εξωτερικού κατόχου.

Unowned Optional

Στο Swift 5.0+ προστέθηκε υποστήριξη για unowned optional (unowned let x: Type?). Αυτός είναι ένας συμβιβασμός: το unowned εγγυάται ότι αν η αναφορά δεν είναι nil, το αντικείμενο ζει. Η συμπεριφορά κατά την απελευθέρωση — crash, όπως στο συνηθισμένο unowned.

Unowned vs Weak: πότε να χρησιμοποιείτε τι

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

ΚριτήριοWeakUnowned
OptionalΝαι (Type?)Όχι (Type)
Μηδενισμός κατά αποδέσμευσηΑυτόματο σε nilΌχι (ρίσκο κρεμάμενου δείκτη)
Τύπος (let/var)Μόνο varlet ή var
ΑπόδοσηΕπιβάρυνση για weak-πίνακαΕλάχιστη (απλός δείκτης)
ΑσφάλειαΑσφαλές (nil ελέγχεται)Ρίσκο EXC_BAD_ACCESS
Εγγύηση διάρκειας ζωήςΔεν απαιτείταιΑπαιτείται ρητή εγγύηση

Πρακτικός κανόνας

Χρησιμοποιήστε weak αν υπάρχει έστω και η παραμικρή αμφιβολία για τη διάρκεια ζωής του αντικειμένου. Το weak είναι ασφαλές, κατανοητό και δεν απαιτεί αποδείξεις. Χρησιμοποιήστε unowned μόνο όταν έχετε αποκλείσει όλα τα σενάρια στα οποία το αντικείμενο θα μπορούσε να απελευθερωθεί νωρίτερα. Τυπικές περιπτώσεις: παιδί που δεν υπάρχει χωρίς γονέα· closure που εκτελείται σύγχρονα· αναφορά σε αντικείμενο εντός του init του.

Σύμφωνα με το Airbnb Swift Style Guide, 2025, σε μεγάλες βάσεις κώδικα συνιστάται η χρήση weak από προεπιλογή και unowned — μόνο με ρητό σχόλιο που εξηγεί την εγγύηση διάρκειας ζωής. Αυτό μειώνει τον κίνδυνο μη προφανών crash κατά την αναδιάρθρωση.

Unowned self σε closures

Τα closures — το δεύτερο συχνότερο σενάριο χρήσης του unowned μετά τις σχέσεις parent-child. Το capture list [unowned self] εφαρμόζεται όταν το self είναι εγγυημένο ότι ζει περισσότερο από το closure. Ας εξετάσουμε τα σωστά και λάθος σενάρια.

Πότε το unowned self είναι ασφαλές

Σύγχρονα closures — sorted, filter, map. Εκτελούνται αμέσως στο τρέχον νήμα, το self σίγουρα ζει. Το capture list με unowned είναι αποδεκτό εδώ και δίνει καθαρότερο κώδικα.

swift
class DataProcessor {
    var items: [Int] = [3, 1, 4, 1, 5]

    func processSorted() {
        // unowned self — sorted εκτελείται σύγχρονα, self εγγυημένα ζωντανό
        let sorted = items.sorted { [unowned self] a, b in
            return self.customCompare(a, b)
        }
    }

    func customCompare(_ a: Int, _ b: Int) -> Bool { return a < b }
}

Πότε το unowned self είναι επικίνδυνο

Ασύγχρονα closures — με καθυστέρηση, αιτήματα δικτύου, κινούμενα σχέδια. Το self μπορεί να απελευθερωθεί μεταξύ της τοποθέτησης του closure και της εκτέλεσής του. Εδώ unowned self → crash. Χρησιμοποιήστε [weak self].

swift
class NetworkLoader {
    func loadData() {
        // ΕΠΙΚΙΝΔΥΝΟ: unowned self σε ασύγχρονο closure
        URLSession.shared.dataTask(with: url) { [unowned self] data, _, _ in
            self.handleResponse(data)  // CRASH αν το self έχει ελευθερωθεί
        }.resume()
    }

    func handleResponse(_ data: Data?) { }

    // ΣΩΣΤΟ: weak self + guard
    func loadDataSafe() {
        URLSession.shared.dataTask(with: url) { [weak self] data, _, _ in
            guard let self else { return }
            self.handleResponse(data)
        }.resume()
    }
}

Θυμηθείτε τον κανόνα: unowned self — μόνο για σύγχρονα closures που εκτελούνται αμέσως. Για ασύγχρονα — πάντα weak self + guard let. Εξαίρεση: αν κρατάτε ρητά μια αναφορά στο αντικείμενο μέχρι την ολοκλήρωση του closure (π.χ. αποθηκεύοντας ένα ισχυρό capture σε άλλη μεταβλητή).

Κίνδυνοι του unowned και πώς να τους αποφύγετε

Το unowned — ένα ισχυρό αλλά επικίνδυνο εργαλείο. Ας εξετάσουμε τα πραγματικά σενάρια όπου το unowned μπορεί να οδηγήσει σε crash και τις μεθόδους ελαχιστοποίησης κινδύνου.

Αναδιάρθρωση και αλλαγή εγγυήσεων

Ο κύριος κίνδυνος του unowned — αλλαγή της επιχειρηματικής λογικής κατά την οποία η εγγύηση διάρκειας ζωής παύει να ισχύει. Ο προγραμματιστής αναδιαρθρώνει τον κώδικα: αλλάζει την ιδιοκτησία, εισάγει καθυστερημένη απελευθέρωση, προσθέτει προσωρινή αποθήκευση — και η unowned αναφορά μετατρέπεται σε ωρολογιακή βόμβα. Ο μεταγλωττιστής δεν θα προειδοποιήσει — μόνο crash στη συσκευή του χρήστη.

Σύσταση: χρησιμοποιήστε unowned μόνο όταν η εγγύηση διάρκειας ζωής είναι προφανής και τεκμηριωμένη. Προσθέστε ένα σχόλιο σε κάθε unowned: γιατί αυτή η αναφορά είναι ασφαλής και υπό ποιες συνθήκες μπορεί να παραβιαστεί.

Unowned σε ιεραρχίες UIKit

UIKit — ζώνη αυξημένου κινδύνου για unowned. Το ViewController μπορεί να απελευθερωθεί ανά πάσα στιγμή κατά την πλοήγηση (pop, dismiss), εκφόρτωση από μνήμη, αλλαγή προσανατολισμού. Εάν μεταβιβάσετε το ViewController σε ένα closure με unowned self — κατά την επιστροφή από το παρασκήνιο ή το τέλος της κίνησης, το self μπορεί να είναι nil.

Βέλτιστες πρακτικές

Για να μειώσετε τον κίνδυνο κατά τη χρήση unowned, ακολουθήστε αυτούς τους κανόνες:

  • Προτιμήστε το weak από προεπιλογή — το weak είναι ασφαλές, το unowned είναι βελτιστοποίηση, όχι πρότυπο
  • Τεκμηριώστε τις εγγυήσεις — για κάθε unowned γράψτε ένα σχόλιο με αιτιολόγηση
  • Αποφύγετε το unowned στο ViewController — ο κύκλος ζωής UIKit είναι απρόβλεπτος για εγγυήσεις unowned
  • Χρησιμοποιήστε unowned μόνο για σύγχρονα closures — sorted, filter, map — ασφαλείς υποψήφιοι
  • Ελέγξτε στο code review — κάθε unowned απαιτεί αιτιολόγηση από τον συγγραφέα του κώδικα
  • Μεταβείτε σε weak στην παραμικρή αμφιβολία — η απώλεια αναγνωσιμότητας (ένα guard let) είναι μικρότερη από ένα crash στην παραγωγή
swift
// Παράδειγμα: τεκμηριωμένη unowned αναφορά με σαφή αιτιολόγηση
class InvoiceLineItem {
    let productName: String
    let price: Decimal

    // unowned Invoice — InvoiceLineItem δεν μπορεί να υπάρξει χωρίς Invoice.
    // Invoice δημιουργεί Item και το διαγράφει κατά τη διαγραφή του.
    // Εγγύηση: Invoice ζει τουλάχιστον όσο το Item.
    unowned let invoice: Invoice

    init(productName: String, price: Decimal, invoice: Invoice) {
        self.productName = productName
        self.price = price
        self.invoice = invoice
    }
}

// Αυτή είναι ισχυρή εγγύηση: Invoice διαγράφει όλα τα Item στο deinit.
// παραβίαση εγγύησης = σφάλμα στην επιχειρηματική λογική που πρέπει να διορθωθεί.

Η τεκμηρίωση των εγγυήσεων — επαγγελματικό πρότυπο. Σε μεγάλα έργα (Airbnb, Uber) το code review απαιτεί αιτιολόγηση κάθε unowned. Αν η εγγύηση δεν είναι προφανής — χρησιμοποιήστε weak. Το σχόλιο στο unowned βοηθά τους μελλοντικούς προγραμματιστές να καταλάβουν γιατί εδώ δεν υπάρχει weak και ποιες συνθήκες μπορούν να σπάσουν την εγγύηση.

Συχνές Ερωτήσεις

Τι συμβαίνει κατά την πρόσβαση σε unowned αναφορά μετά την απελευθέρωση του αντικειμένου;

Runtime crash με EXC_BAD_ACCESS. Η Swift δεν ελέγχει την εγκυρότητα της unowned αναφοράς κατά την πρόσβαση — είναι απλώς ένας "ακατέργαστος" δείκτης. Εάν το αντικείμενο έχει απελευθερωθεί, η μνήμη έχει αντικατασταθεί και η πρόσβαση σε αυτήν καταλήγει σε crash. Αυτή είναι μια μη αναχαιτίσιμη εξαίρεση (όχι try-catch).

Μπορεί το unowned να χρησιμοποιηθεί με πρωτόκολλα;

Ναι, εάν το πρωτόκολλο κληρονομεί από το AnyObject. Το unowned λειτουργεί με όλους τους τύπους αναφοράς: κλάσεις, πρωτόκολλα AnyObject, αντικείμενα Objective-C. Οι τύποι τιμών (struct, enum) δεν υποστηρίζουν unowned επειδή δεν συμμετέχουν στο ARC.

Πότε το unowned είναι ασφαλέστερο από το weak;

Όταν η εγγύηση διάρκειας ζωής είναι απόλυτη και προφανής — το unowned είναι ασφαλέστερο από άποψη σχεδιασμού: δεν απαιτεί unwrap, δεν μπορεί να είναι nil, δεν κρύβει σφάλματα. Εάν το αντικείμενο δεν μπορεί να υπάρξει χωρίς γονέα, το unowned το καθιστά ρητό συμβόλαιο, ενώ το weak θολώνει την εγγύηση.

Υπάρχει διαφορά απόδοσης μεταξύ unowned και weak;

Ναι: το unowned είναι ταχύτερο επειδή δεν απαιτεί πρόσβαση στον weak-πίνακα runtime για μηδενισμό. Στις περισσότερες εφαρμογές η διαφορά δεν είναι αισθητή, αλλά σε σενάρια υψηλού φόρτου με εκατομμύρια προσβάσεις, το unowned μπορεί να είναι 10–20% ταχύτερο στην ανάγνωση.

Πώς επηρεάζει η αναδιάρθρωση τις εγγυήσεις unowned;

Αναδιάρθρωση — ο κύριος κίνδυνος για το unowned. Η αλλαγή στη διάρκεια ζωής του αντικειμένου (προσωρινή αποθήκευση, ασύγχρονες λειτουργίες, επαναχρησιμοποίηση) μπορεί να παραβιάσει την εγγύηση. Ο μεταγλωττιστής δεν θα προειδοποιήσει. Λύση: μεταβείτε σε weak κατά την αλλαγή αρχιτεκτονικής ή προσθέστε σχόλιο προειδοποίησης.

Περίληψη

  • Unowned Reference — μη κατέχουσα αναφορά χωρίς μηδενισμό· non-optional, δεν αυξάνει το retain count
  • Εγγύηση — απαιτεί ρητή απόδειξη ότι το αντικείμενο ζει τουλάχιστον όσο ο κώδικας που αναφέρεται σε αυτό
  • Σύνταξηunowned let ή unowned var· μπορεί να είναι non-optional και optional (Swift 5.0+)
  • Unowned vs Weak — το unowned είναι ταχύτερο και καθαρότερο, αλλά το weak είναι ασφαλέστερο· weak — προεπιλεγμένη επιλογή
  • Closures — unowned self μόνο για σύγχρονα closures· ασύγχρονα απαιτούν [weak self]
  • Τεκμηρίωση — κάθε unowned θα πρέπει να έχει σχόλιο με αιτιολόγηση της εγγύησης
  • Σύσταση — σε περίπτωση αμφιβολίας επιλέξτε weak· unowned — για ρητά και τεκμηριωμένα συμβόλαια

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης