@ObservedObject: τι είναι, πώς λειτουργεί και παραδείγματα

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

Το @ObservedObject είναι ένα Property Wrapper στο SwiftUI για την παρατήρηση μιας παρουσίας ObservableObject που μεταβιβάζεται από έξω. Σε αντίθεση με το @StateObject, το @ObservedObject δεν δημιουργεί αντικείμενο — εγγράφεται στις αλλαγές ενός υπάρχοντος. Σύμφωνα με το Apple Developer Documentation (2025), το @ObservedObject χρησιμοποιείται σε θυγατρικά view που πρέπει να παρακολουθούν δεδομένα που ανήκουν στον γονέα. @ObservedObject παρέχει αντιδραστική σύνδεση χωρίς διαχείριση του κύκλου ζωής του αντικειμένου.

Βασικά Σημεία

  • @ObservedObject — Property Wrapper για παρατήρηση ObservableObject χωρίς ιδιοκτησία
  • Χωρίς δημιουργία — το αντικείμενο μεταβιβάζεται από το γονικό view ή το περιβάλλον
  • @Published — ιδιότητες εντός ObservableObject των οποίων τις αλλαγές παρακολουθεί το SwiftUI
  • Επανασχεδίαση — όταν αλλάζει μια @Published ιδιότητα, το SwiftUI ενημερώνει όλα τα εγγεγραμμένα view
  • Μην το μπερδεύετε με το @StateObject — το @ObservedObject δεν εγγυάται μοναδική παρουσία

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

@ObservedObject είναι ένα Property Wrapper που εγγράφει το view στις αλλαγές του ObservableObject. Το ObservableObject είναι ένα πρωτόκολλο από το πλαίσιο Combine που απαιτεί την υλοποίηση του publisher objectWillChange. Όταν οποιαδήποτε ιδιότητα με την ένδειξη @Published αλλάζει εντός του ObservableObject, ο publisher στέλνει ένα σήμα και το SwiftUI επανασχεδιάζει όλα τα view που είναι εγγεγραμμένα μέσω @ObservedObject.

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

Το @ObservedObject είναι κατάλληλο για σενάρια κοινής χρήσης δεδομένων: μοντέλο χρήστη, κοινές ρυθμίσεις, κατάσταση σύνδεσης με τον διακομιστή. Όταν πολλαπλά view σε διαφορετικά επίπεδα της ιεραρχίας πρέπει να εμφανίζουν τα ίδια δεδομένα, το @ObservedObject σε κάθε view δημιουργεί ανεξάρτητες αλλά συντονισμένες εγγραφές σε μία πηγή.

@ObservedObject vs @StateObject: βασικές διαφορές

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

Χαρακτηριστικό@StateObject@ObservedObject
Δημιουργία αντικειμένουΝαι, κατά την αρχικοποίηση του viewΌχι, λαμβάνει έτοιμο
ΙδιοκτησίαΤρέχον viewΓονικό στοιχείο
Μοναδική παρουσίαΝαι, σε όλο τον κύκλο ζωήςΌχι, μπορεί να αντικατασταθεί
Επαναδημιουργία κατά την απόδοσηΌχι, διατηρείταιΕξαρτάται από τον γονέα
Πού να χρησιμοποιείταιΡιζικό view-ιδιοκτήτηςΘυγατρικά view

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

Πώς το @ObservedObject παρακολουθεί αλλαγές

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

swift
class WeatherService: ObservableObject {
    @Published var temperature: Double = 22.0
    @Published var city: String = "Moscow"
}

struct WeatherView: View {
    @ObservedObject var weather: WeatherService

    var body: some View {
        VStack {
            Text("\\(weather.city)")
            Text("\\(weather.temperature)°C")
        }
    }
}

Στη λίστα, το WeatherService είναι ένα ObservableObject με δύο @Published ιδιότητες. Το WeatherView δηλώνει @ObservedObject var weather: WeatherService, λαμβάνοντας την παρουσία από τον γονέα. Όταν η temperature αλλάζει, το objectWillChange ενεργοποιείται πριν από τον ορισμό της νέας τιμής, το SwiftUI επανασχεδιάζει το WeatherView και εμφανίζεται η τρέχουσα θερμοκρασία. Η εγγραφή διαχειρίζεται αυτόματα από το SwiftUI — ο προγραμματιστής δεν χρειάζεται να καλέσει sink ή dispose.

Μοτίβα χρήσης @ObservedObject

Πρώτο μοτίβο — μεταβίβαση μοντέλου μέσω αρχικοποιητή. Ο γονέας δημιουργεί το ObservableObject μέσω @StateObject και το μεταβιβάζει στα θυγατρικά view ως @ObservedObject. Πρόκειται για μια τυπική ιεραρχική μεταφορά δεδομένων όπου το ριζικό view διαχειρίζεται τον κύκλο ζωής του μοντέλου και όλα τα ένθετα στοιχεία εγγράφονται στις αλλαγές.

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

Τρίτο μοτίβο — σύνθεση πολλαπλών ObservableObject. Σε σύνθετες εφαρμογές, το view μπορεί να παρατηρεί πολλαπλά αντικείμενα: @ObservedObject var user: UserService, @ObservedObject var network: NetworkMonitor. Αυτό διαχωρίζει την ευθύνη μεταξύ υπηρεσιών και διατηρεί τη δυνατότητα δοκιμής κάθε στοιχείου.

swift
struct DashboardView: View {
    @ObservedObject var user: UserViewModel
    @ObservedObject var network: NetworkMonitor

    var body: some View {
        VStack {
            Text("Καλώς ορίσατε, \\(user.name)")
            HStack {
                Circle()
                    .fill(network.isConnected ? Color.green : Color.red)
                    .frame(width: 10, height: 10)
            }
        }
    }
}

DashboardView παρατηρεί το UserViewModel και το NetworkMonitor. Κάθε αντικείμενο είναι υπεύθυνο για τον δικό του τομέα δεδομένων και ειδοποιεί ανεξάρτητα το view για αλλαγές. Εάν το δίκτυο αποσυνδεθεί, το NetworkMonitor αλλάζει το isConnected και το SwiftUI επανασχεδιάζει το DashboardView, ενημερώνοντας το χρώμα του δείκτη. Η σύνθεση ObservableObject είναι ο προτιμώμενος τρόπος οργάνωσης δεδομένων σε εφαρμογές SwiftUI.

@Published: η σύνδεση ObservableObject και SwiftUI

@Published είναι ένα Property Wrapper από το Combine που προσθέτει αυτόματα έναν εκδότη σε μια ιδιότητα εντός του ObservableObject. Όταν η @Published ιδιότητα αλλάζει, το Combine δημιουργεί ένα συμβάν μέσω του publisher objectWillChange. Το SwiftUI εγγράφεται σε αυτόν τον publisher όταν χρησιμοποιεί @ObservedObject ή @StateObject και επανασχεδιάζει το view σε κάθε νέα τιμή.

Το @Published υποστηρίζει όλους τους τύπους, συμπεριλαμβανομένων των προαιρετικών, συλλογών και προσαρμοσμένων δομών. Ωστόσο, για συλλογές (πίνακες, λεξικά) το SwiftUI παρακολουθεί μόνο την αντικατάσταση της αναφοράς, όχι την αλλαγή περιεχομένου. Για να εντοπίσετε την προσθήκη ή αφαίρεση ενός στοιχείου, πρέπει να επαναναθέσετε ολόκληρη τη συλλογή ή να χρησιμοποιήσετε ObservableObject με μη αυτόματη κλήση objectWillChange.send().

Σημαντική λεπτομέρεια: @Published πρέπει να βρίσκεται μόνο εντός μιας κλάσης που υλοποιεί το ObservableObject. Η χρήση @Published εκτός ObservableObject θα προκαλέσει σφάλμα μεταγλώττισης. Επίσης, το @Published δεν μπορεί να εφαρμοστεί σε ιδιότητες τεμπέλικης αρχικοποίησης (lazy var) ή υπολογιζόμενες ιδιότητες (computed property).

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

Το πιο κρίσιμο λάθος — η χρήση @ObservedObject για τη δημιουργία αντικειμένου. Εάν γράψετε @ObservedObject var model = UserViewModel() στο γονικό view, σε κάθε απόδοση θα δημιουργείται μια νέα παρουσία UserViewModel. Τα δεδομένα θα χαθούν και οι @Published εγγραφές θα αναδημιουργηθούν. Χρησιμοποιείτε πάντα @StateObject για δημιουργία και @ObservedObject μόνο για λήψη έτοιμου αντικειμένου.

Δεύτερο λάθος — αλλαγή @Published ιδιοτήτων εκτός του κύριου νήματος. Το ObservableObject χρησιμοποιεί το Combine, το οποίο απαιτεί την αποστολή αλλαγών στο κύριο νήμα (main actor). Εάν αλλάξετε το @Published σε μια ουρά παρασκηνίου, το SwiftUI μπορεί να επανασχεδιάσει το view σε ακατάλληλη στιγμή, προκαλώντας race conditions. Χρησιμοποιήστε DispatchQueue.main.async ή @MainActor για ενημέρωση.

Τρίτο πρόβλημα — κυκλικές ενημερώσεις. Εάν μια αλλαγή @Published περιλαμβάνει παρενέργειες που αλλάζουν ξανά το @Published, δημιουργείται ένας ατελείωτος βρόχος επανασχεδίασης. Λύση: χρησιμοποιήστε σημαίες προστασίας (isUpdating) ή διαχωρίστε τη λογική σε διαφορετικά ObservableObject με σαφή όρια ευθύνης.

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

Μπορεί το @ObservedObject να είναι προαιρετικό;

Ναι, το SwiftUI υποστηρίζει @ObservedObject var model: UserViewModel?. Ωστόσο, το view δεν θα εγγράφεται σε αλλαγές όσο το αντικείμενο είναι nil. Κατά την ανάθεση τιμής, η εγγραφή ενεργοποιείται αυτόματα.

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

@ObservedObject λαμβάνει το αντικείμενο μέσω αρχικοποιητή, @EnvironmentObject μέσω SwiftUI Environment. Το @EnvironmentObject δεν απαιτεί ρητή μεταβίβαση μέσω κατασκευαστών, αλλά το αντικείμενο πρέπει να εισαχθεί στο ανώτερο επίπεδο της ιεραρχίας.

Πώς να ειδοποιήσω χειροκίνητα το SwiftUI για αλλαγή του ObservableObject;

Καλέστε το objectWillChange.send() πριν από την αλλαγή της ιδιότητας. Αυτό είναι χρήσιμο εάν το @Published δεν είναι κατάλληλο (για παράδειγμα, για υπολογιζόμενες ιδιότητες ή λειτουργίες συλλογών όπου η αλλαγή πρέπει να αναφερθεί πριν από τη μετάλλαξη).

Γιατί το @ObservedObject δεν επανασχεδιάζει το view όταν αλλάζει το περιεχόμενο ενός πίνακα;

@ObservedObject και @Published παρακολουθούν την αντικατάσταση της αναφοράς, όχι τη μετάλλαξη του περιεχομένου της συλλογής. Για επανασχεδίαση πρέπει να επαναναθέσετε τον πίνακα: items.append(newItem) → items = items ή να χρησιμοποιήσετε objectWillChange.send() πριν από τη μετάλλαξη.

Μπορεί να χρησιμοποιηθεί το @ObservedObject σε μια δομή που δεν υλοποιεί το View;

Όχι, το @ObservedObject είναι ένα SwiftUI Property Wrapper διαθέσιμο μόνο εντός τύπων που υλοποιούν το πρωτόκολλο View. Για συνηθισμένες δομές, χρησιμοποιήστε το Combine απευθείας με το ObservableObjectPublisher.

Σύνοψη

  • @ObservedObject — Property Wrapper για παρατήρηση ObservableObject χωρίς ιδιοκτησία
  • @StateObject — δημιουργεί αντικείμενο, @ObservedObject — παρατηρεί υπάρχον
  • @Published — αυτόματος εκδότης για ιδιότητες ObservableObject
  • Εγγραφή — το SwiftUI διαχειρίζεται αυτόματα την εγγραφή Combine όταν χρησιμοποιεί @ObservedObject
  • Σύνθεση — το view μπορεί να παρατηρεί πολλαπλά ObservableObject ταυτόχρονα
  • Main actor — οι @Published ιδιότητες πρέπει να αλλάζουν μόνο στο κύριο νήμα
  • EnvironmentObject — εναλλακτική του @ObservedObject για σιωπηρή μεταβίβαση μέσω περιβάλλοντος

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

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

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

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