@ObservedObject: τι είναι, παρακολούθηση αντικειμένων και ενημέρωση View

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

@ObservedObject είναι ένα property wrapper στο SwiftUI που επιτρέπει στο View να παρακολουθεί αλλαγές σε ένα ObservableObject που δημιουργήθηκε σε άλλο σημείο της ιεραρχίας. Σε αντίθεση με το @StateObject, το @ObservedObject δεν δημιουργεί αντικείμενο — απλώς εγγράφεται στον publisher objectWillChange και επανασχεδιάζει το View κατά την ενημέρωση των @Published ιδιοτήτων. Αυτό καθιστά το @ObservedObject τη σωστή επιλογή για θυγατρικά View που λαμβάνουν δεδομένα από τον γονέα μέσω αρχικοποιητή. Σύμφωνα με το άρθρο του Paul Hudson — Hacking with Swift (2025), η τυπική αρχιτεκτονική μιας εφαρμογής SwiftUI χτίζεται ως εξής: το ριζικό View χρησιμοποιεί @StateObject για να δημιουργήσει view model και όλα τα θυγατρικά View το λαμβάνουν μέσω @ObservedObject, εξασφαλίζοντας μια ενιαία πηγή αλήθειας χωρίς διπλασιασμό δεδομένων.

Κύρια σημεία

  • @ObservedObject — property wrapper για παρακολούθηση ObservableObject που δημιουργήθηκε στο γονικό View.
  • Δεν κατέχει το αντικείμενο — σε αντίθεση με το @StateObject, το @ObservedObject δεν διαχειρίζεται τον κύκλο ζωής του αντικειμένου.
  • Εγγραφή σε αλλαγές — κατά την αλλαγή των @Published ιδιοτήτων, το View επανασχεδιάζεται αυτόματα.
  • Μετάδοση μέσω αρχικοποιητή — το αντικείμενο μεταδίδεται στο θυγατρικό View μέσω παραμέτρου αρχικοποιητή.
  • iOS 13+ — το @ObservedObject είναι διαθέσιμο από την πρώτη έκδοση του SwiftUI, σε αντίθεση με το @StateObject (iOS 14+).

Τι είναι το @ObservedObject στο SwiftUI

@ObservedObject είναι ένα property wrapper που εγγράφει το View στις αλλαγές ObservableObject. Όταν το αντικείμενο που σημειώνεται με @ObservedObject αλλάζει οποιαδήποτε από τις ιδιότητές του που δηλώνονται με @Published, το SwiftUI επανασχεδιάζει αυτόματα το View. Το @ObservedObject δεν δημιουργεί αντικείμενο — απλώς δημιουργεί μια σύνδεση μεταξύ μιας υπάρχουσας παρουσίας ObservableObject και του View που πρέπει να αντιδράσει στις αλλαγές του.

Η βασική διαφορά μεταξύ @ObservedObject και @StateObject — είναι η ιδιοκτησία. Το @ObservedObject υποθέτει ότι το αντικείμενο δημιουργήθηκε και αποθηκεύτηκε κάπου ψηλότερα στην ιεραρχία View. Το θυγατρικό View λαμβάνει μια αναφορά σε αυτό το αντικείμενο μέσω αρχικοποιητή και απλώς το παρακολουθεί. Εάν το θυγατρικό View αναδημιουργηθεί, θα λάβει την ίδια αναφορά από τον γονέα — τα δεδομένα δεν θα χαθούν.

Σύμφωνα με το Apple Developer Documentation — SwiftUI (2025), το @ObservedObject είναι διαθέσιμο από το iOS 13, καθιστώντας το τη μοναδική επιλογή για παρακολούθηση ObservableObject σε έργα που υποστηρίζουν παλαιότερες εκδόσεις iOS. Στο iOS 14+ το @StateObject προτιμάται για τη δημιουργία αντικειμένων, αλλά το @ObservedObject παραμένει σχετικό για τη μετάδοση υπαρχόντων αντικειμένων.

Πώς λειτουργεί το @ObservedObject

Ο μηχανισμός @ObservedObject βασίζεται στο πρωτόκολλο ObservableObject από το framework Combine. Κάθε κλάση που συμμορφώνεται με το ObservableObject λαμβάνει αυτόματα έναν publisher objectWillChange που στέλνει σήμα πριν από την αλλαγή οποιασδήποτε @Published ιδιότητας. Το SwiftUI εγγράφεται σε αυτόν τον publisher μέσω @ObservedObject και μετά τη λήψη του σήματος, σημειώνει το View ως απαιτούν επανασχεδιασμό.

swift
class TaskViewModel: ObservableObject {
    @Published var tasks: [Task] = []
    @Published var isLoading = false
    
    func loadTasks() async {
        isLoading = true
        // λήψη δεδομένων
        isLoading = false
    }
}

struct TaskListView: View {
    @ObservedObject var viewModel: TaskViewModel
    
    var body: some View {
        List(viewModel.tasks) { task in
            Text(task.title)
        }
        .task { await viewModel.loadTasks() }
    }
}

Όταν το γονικό View μεταδίδει το viewModel στο TaskListView μέσω αρχικοποιητή, το SwiftUI δημιουργεί μια σύνδεση μεταξύ του αντικειμένου και του View. Κατά την αλλαγή του πίνακα tasks ή της σημαίας isLoading, το SwiftUI επανασχεδιάζει το TaskListView. Το αντικείμενο παραμένει αμετάβλητο — αποθηκεύεται στο γονικό View μέσω @StateObject.

@ObservedObject vs @StateObject: πότε να χρησιμοποιείτε τι

Η διαφορά μεταξύ @ObservedObject και @StateObject — είναι η διαφορά μεταξύ παρατηρητή και ιδιοκτήτη. Το @StateObject δημιουργεί αντικείμενο και διαχειρίζεται τον κύκλο ζωής του. Το @ObservedObject παρακολουθεί μόνο το αντικείμενο που δημιουργήθηκε και αποθηκεύτηκε σε άλλο μέρος. Η επιλογή μεταξύ τους καθορίζεται από την ευθύνη του View για τα δεδομένα.

ΣενάριοΣύστασηΑιτία
View δημιουργεί δεδομένα@StateObjectView κατέχει το αντικείμενο και είναι υπεύθυνο για τον κύκλο ζωής του
View λαμβάνει δεδομένα@ObservedObjectView μόνο παρακολουθεί, το αντικείμενο ζει στον γονέα
Υποστήριξη iOS 13@ObservedObject@StateObject μη διαθέσιμο, χρησιμοποιήστε @ObservedObject με χειροκίνητη διαχείριση
Επαναχρησιμοποιήσιμο στοιχείο@ObservedObjectΤο στοιχείο δεν πρέπει να δημιουργεί δεδομένα — τα λαμβάνει από έξω

Κύριος κανόνας: εάν το View δημιουργεί αντικείμενο — @StateObject. Εάν το View λαμβάνει αντικείμενο — @ObservedObject. Η παραβίαση αυτού του κανόνα προς την πλευρά του @ObservedObject για τη δημιουργία αντικειμένου οδηγεί σε απώλεια δεδομένων κατά την ανακατασκευή του View. Η παραβίαση προς την πλευρά του @StateObject για τη λήψη αντικειμένου δημιουργεί μια διπλότυπη παρουσία, ανεξάρτητη από τον γονέα.

Παραδείγματα χρήσης @ObservedObject

Το τυπικό σενάριο χρήσης @ObservedObject — μια λίστα εργασιών, όπου το ριζικό View δημιουργεί ένα view model και το κελί της λίστας το λαμβάνει μέσω @ObservedObject. Κάθε κελί μπορεί να καλέσει μεθόδους του view model και οι αλλαγές εμφανίζονται αυτόματα σε ολόκληρη τη λίστα, επειδή όλα τα κελιά παρακολουθούν το ίδιο αντικείμενο.

swift
struct TaskRow: View {
    @ObservedObject var viewModel: TaskViewModel
    let task: Task
    
    var body: some View {
        HStack {
            Text(task.title)
            Spacer()
            Button("Έτοιμο") {
                viewModel.completeTask(task)
            }
        }
    }
}

struct TaskListContainer: View {
    @StateObject var viewModel = TaskViewModel()
    
    var body: some View {
        List(viewModel.tasks) { task in
            TaskRow(viewModel: viewModel, task: task)
        }
    }
}

Σε αυτό το παράδειγμα, το TaskListContainer δημιουργεί viewModel μέσω @StateObject και κάθε TaskRow το λαμβάνει μέσω @ObservedObject. Όταν ο χρήστης κάνει κλικ στο “Done” σε οποιαδήποτε γραμμή, το viewModel.completeTask αλλάζει την published ιδιότητα και όλα τα View που παρακολουθούν αυτό το αντικείμενο ενημερώνονται αυτόματα.

Συνηθισμένα λάθη με @ObservedObject

Το πιο συνηθισμένο λάθος — η χρήση @ObservedObject για τη δημιουργία αντικειμένου μέσα στο View. Όταν το View ανακατασκευάζεται (π.χ. κατά την αλλαγή state), το SwiftUI δημιουργεί μια νέα παρουσία ObservableObject, οδηγώντας σε απώλεια όλων των συσσωρευμένων δεδομένων. Αυτό το λάθος είναι ιδιαίτερα επώδυνο στο NavigationStack, όπου ο χρήστης μπορεί να συμπληρώσει μια φόρμα και να χάσει δεδομένα κατά την επιστροφή.

Λάθος: @ObservedObject αντί για @StateObject

swift
// ❌ Απώλεια δεδομένων: το @ObservedObject δεν διατηρεί το αντικείμενο
struct FormView: View {
    @ObservedObject var formVM = FormViewModel()
    // Νέο formVM δημιουργείται σε κάθε ανακατασκευή View!
}

// ✅ Σωστά: το @StateObject διατηρεί το αντικείμενο
struct FormView: View {
    @StateObject var formVM = FormViewModel()
    // Αντικείμενο δημιουργήθηκε μία φορά για τη διάρκεια ζωής του View
}

Λάθος: μετάδοση @StateObject εκεί που χρειάζεται @ObservedObject

Εάν το θυγατρικό View δηλώνει το ίδιο ObservableObject μέσω @StateObject, δημιουργεί ένα ανεξάρτητο αντίγραφο. Οι αλλαγές στο γονικό αντικείμενο δεν θα είναι ορατές στο θυγατρικό και το αντίστροφο. Πάντα χρησιμοποιείτε @ObservedObject για θυγατρικά View που λαμβάνουν το αντικείμενο από έξω.

Εναλλακτικές για @ObservedObject στο SwiftUI

Στο σύγχρονο SwiftUI υπάρχουν αρκετές εναλλακτικές για το @ObservedObject, η καθεμία με τα πλεονεκτήματά της. Η επιλογή εξαρτάται από την αρχιτεκτονική της εφαρμογής, την έκδοση iOS και το συγκεκριμένο σενάριο χρήσης.

  • @EnvironmentObject — επιτρέπει τη λήψη αντικειμένου από το περιβάλλον SwiftUI χωρίς ρητή μετάδοση μέσω αρχικοποιητή. Βολικό για αντικείμενα που χρειάζονται σε πολλές οθόνες, αλλά απαιτεί ρητή έγχυση μέσω .environmentObject().
  • @State + @Binding — για απλούς τύπους τιμών δεν χρειάζονται ObservableObject. Χρησιμοποιήστε @State για αποθήκευση και @Binding για μετάδοση σε θυγατρικά View.
  • @AppStorage — για τιμές UserDefaults που πρέπει να συγχρονίζονται αυτόματα με το View.
  • @SceneStorage — για αποθήκευση προσωρινής κατάστασης μεταξύ επανεκκινήσεων σκηνής (π.χ. θέση σε λίστα).

Η επιλογή μεταξύ @ObservedObject και @EnvironmentObject — είναι θέμα στυλ και αρχιτεκτονικής. Το @ObservedObject δείχνει ρητά τις εξαρτήσεις του View μέσω αρχικοποιητή, καθιστώντας τον κώδικα πιο προβλέψιμο. Το @EnvironmentObject είναι βολικό για βαθιές ιεραρχίες, αλλά κρύβει τις εξαρτήσεις, γεγονός που μπορεί να δυσκολέψει τον εντοπισμό σφαλμάτων.

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

Μπορεί να χρησιμοποιηθεί το @ObservedObject χωρίς @StateObject στον γονέα;

Ναι, εάν το αντικείμενο δημιουργείται και αποθηκεύεται εκτός SwiftUI — για παράδειγμα, στο AppDelegate ή singleton. Σε αυτήν την περίπτωση, το @ObservedObject απλώς εγγράφεται στις αλλαγές του υπάρχοντος αντικειμένου. Ωστόσο, για αντικείμενα που δημιουργούνται εντός της ιεραρχίας SwiftUI, απαιτείται πάντα ένα @StateObject κάπου ψηλότερα.

Γιατί το @ObservedObject μερικές φορές δεν ενημερώνει το View;

Η πιο πιθανή αιτία — η ιδιότητα αλλάζει όχι μέσω @Published ή δεν αλλάζει το ίδιο το αντικείμενο, αλλά η εσωτερική του δομή χωρίς κλήση του objectWillChange. Για συλλογές, χρησιμοποιήστε ανάθεση νέου αντιγράφου: array.append() δεν είναι αρκετό — πρέπει να αναθέσετε ξανά ολόκληρο τον πίνακα μέσω array = array + [element].

Επηρεάζει το @ObservedObject την απόδοση;

Το @ObservedObject από μόνο του δεν δημιουργεί σημαντικό φορτίο. Προβλήματα προκύπτουν με συχνές αλλαγές των @Published ιδιοτήτων — κάθε αλλαγή πυροδοτεί επανασχεδιασμό όλων των View που παρακολουθούν. Για βελτιστοποίηση, χρησιμοποιήστε EquatableView, μειώστε τον αριθμό των published ιδιοτήτων και αποφύγετε περιττές ενημερώσεις.

Σε τι διαφέρει το @ObservedObject από το @Binding;

@ObservedObject παρακολουθεί ολόκληρη την κλάση ObservableObject και επανασχεδιάζει το View σε κάθε αλλαγή των published ιδιοτήτων του. @Binding δημιουργεί μια αμφίδρομη σύνδεση με μια συγκεκριμένη τιμή (String, Int, Bool) και επιτρέπει την ανάγνωση και εγγραφή της. Το @Binding είναι ελαφρύτερο και δεν απαιτεί ObservableObject.

Μπορεί να συνδυαστεί το @ObservedObject με @Published στην ίδια κλάση;

Ναι, αυτό είναι ένα τυπικό μοτίβο. Το @Published μέσα στο ObservableObject ενσωματώνεται αυτόματα με το @ObservedObject. Κάθε @Published ιδιότητα προσθέτει έναν παρατηρητή στον publisher objectWillChange. Κατά την αλλαγή οποιασδήποτε από αυτές, όλα τα View με @ObservedObject για αυτό το αντικείμενο επανασχεδιάζονται.

Περίληψη

  • @ObservedObject — property wrapper για παρακολούθηση ObservableObject που δημιουργήθηκε σε άλλο σημείο της ιεραρχίας.
  • Δεν κατέχει το αντικείμενο — σε αντίθεση με το @StateObject, το @ObservedObject δεν διαχειρίζεται τον κύκλο ζωής και δεν δημιουργεί αντικείμενο.
  • Εγγραφή μέσω Combine — το SwiftUI εγγράφεται αυτόματα στον publisher objectWillChange του ObservableObject.
  • iOS 13+ — το @ObservedObject είναι διαθέσιμο από την πρώτη έκδοση του SwiftUI, σημαντικό για έργα με παλαιά υποστήριξη.
  • Μετάδοση μέσω αρχικοποιητή — το αντικείμενο μεταδίδεται ρητά στο θυγατρικό View, καθιστώντας τις εξαρτήσεις διαφανείς.
  • Σφάλμα ιδιοκτησίας — η χρήση @ObservedObject για δημιουργία αντικειμένου οδηγεί σε απώλεια δεδομένων κατά την ανακατασκευή του View.
  • Εναλλακτικές — @EnvironmentObject για έγχυση μέσω περιβάλλοντος, @State/@Binding για τύπους τιμών.

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

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

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

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