@AppStorage στο SwiftUI — τι είναι, UserDefaults και αποθήκευση ρυθμίσεων

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

@AppStorage στο SwiftUI — property wrapper για εργασία με UserDefaults, που συγχρονίζει αυτόματα την τιμή με το UI. Όταν αλλάζει μια ιδιότητα που δηλώνεται μέσω @AppStorage, η νέα τιμή αποθηκεύεται αμέσως στο UserDefaults, και όταν το UserDefaults αλλάζει από εξωτερικά — από ένα widget ή μια επέκταση — το View ανασχεδιάζεται αυτόματα. Σύμφωνα με την Apple Developer Documentation (2025), το @AppStorage υποστηρίζει String, Int, Double, Bool, Data, URL και τις προαιρετικές εκδόσεις τους, παρέχοντας αντιδραστική αποθήκευση ρυθμίσεων χρήστη χωρίς χειροκίνητο κώδικα παρακολούθησης.

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

  • @AppStorage — property wrapper για αντιδραστική εργασία με UserDefaults στο SwiftUI
  • Αυτόματη αποθήκευση — η τιμή εγγράφεται στο UserDefaults σε κάθε αλλαγή
  • Αυτόματη ενημέρωση UI — το View ανασχεδιάζεται όταν το UserDefaults αλλάζει από οποιαδήποτε πηγή
  • Υποστηριζόμενοι τύποι: String, Int, Double, Bool, Data, URL και προαιρετικές εκδόσεις
  • Προκαθορισμένη τιμή ορίζεται στη δήλωση και χρησιμοποιείται κατά την πρώτη εκκίνηση

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

@AppStorage είναι ένα property wrapper που εισήχθηκε από την Apple στο iOS 14, το οποίο συνδέει μια ιδιότητα View με ένα κλειδί στο UserDefaults. Κατά την ανάγνωση της ιδιότητας, το SwiftUI φορτώνει την τιμή από το UserDefaults βάσει του καθορισμένου κλειδιού. Κατά την εγγραφή — αποθηκεύει τη νέα τιμή και ειδοποιεί το View για την ανάγκη επανασχεδίασης.

Πριν από την εμφάνιση του @AppStorage, οι πραγματοποιητές έπρεπε να διαβάζουν χειροκίνητα το UserDefaults στο onAppear, να εγγράφονται στην ειδοποίηση UserDefaults.didChangeNotification και να ενημερώνουν το @State σε αλλαγές. Το @AppStorage αυτοματοποιεί όλο τον κύκλο: μια δήλωση σε μία γραμμή αντικαθιστά 15–20 γραμμές boilerplate κώδικα. Επιπλέον, το @AppStorage παρέχει αμφίδρομη συγχρονισμό — εάν η τιμή UserDefaults αλλάξει από άλλη διεργασία (π.χ., App Extension ή Widget), το View θα λάβει πάντα την ενημέρωση.

Αρχιτεκτονικά, το @AppStorage υλοποιείται ως DynamicProperty, επιτρέποντας στο SwiftUI να παρακολουθεί εξαρτήσεις και να ανασχεδιάζει το View όταν η παρατηρούμενη τιμή αλλάζει. Αυτό το καθιστά ιδανικό για την αποθήκευση ρυθμίσεων χρήστη: γλώσσα διεπαφής, ενεργοποίηση/απενεργοποίηση λειτουργιών, τελευταία επιλεγμένη καρτέλα, όνομα χρήστη.

@AppStorage vs UserDefaults: σύγκριση

Αν και το @AppStorage χρησιμοποιεί το UserDefaults κάτω από την καπότα, οι προσεγγίσεις στην αποθήκευση διαφέρουν ουσιωδώς. Το UserDefaults είναι ένα API χαμηλού επιπέδου που απαιτεί χειροκίνητη διαχείριση ανάγνωσης, εγγραφής και ειδοποιήσεων αλλαγής. Το @AppStorage είναι μια αφαίρεση SwiftUI που παρέχει αντιδραστική συμπεριφορά αμέσως από το κουτί.

Το UserDefaults είναι κατάλληλο για εφάπαξ λειτουργίες: φόρτωση ρυθμίσεων κατά την εκκίνηση της εφαρμογής, εγγραφή αναλυτικών, αποθήκευση τοκενιών στην κρυφή μνήμη. @AppStorage — για ρυθμίσεις που πρέπει να ενημερώνουν αντιδραστικά το UI: διακόπτες θεμάτων, επιλογή γλώσσας, αποθήκευση κατάστασης διεπαφής. Η απευθείας χρήση του UserDefaults μέσα σε ένα View είναι αντιπρότυπο, επειδή το View δεν μανθαίνει για αλλαγές χωρίς επιπλέον εγγραφή.

Παράμετρος@AppStorageUserDefaults
ΑντιδραστικότηταΑυτόματηΑπαιτεί εγγραφή σε ειδοποιήσεις
Boilerplate1 γραμμή ανά ιδιότητα15–20 γραμμές ανά ιδιότητα
ΤύποιString, Int, Double, Bool, Data, URLΌλοι οι τύποι + αρχείο αντικείμενα
Προσαρμοσμένοι τύποιΜέσω RawRepresentableΜέσω NSKeyedArchiver
App ExtensionΑυτόματος συγχρονισμόςΧειροκίνητη εγγραφή

Για απλές ρυθμίσεις με αντιδραστικό UI, το @AppStorage είναι η προτιμώμενη επιλογή. Για σύνθετα δεδομένα (πίνακες, λεξικά, προσαρμοσμένα αντικείμενα) χρησιμοποιήστε τον συνδυασμό UserDefaults με @State και χειροκίνητη εγγραφή σε αλλαγές, ή μεταβείτε σε SwiftData / Core Data για δομημένη αποθήκευση.

Υποστηριζόμενοι τύποι δεδομένων

Το @AppStorage υποστηρίζει τους στανδαρτικούς τύπους που το UserDefaults μπορεί να σειριαλοποιήσει απευθείας: String, Int, Double, Bool, Data, URL. Για κάθε τύπο υπάρχει μια προαιρετική εκδορή (String?, Int?, Double?, Bool?, Data?, URL?), που επιτρέπει τη διάκριση μεταξύ «δεν έχει οριστεί» και «κενή τιμή».

Για την αποθήκευση προσαρμοσμένων τύπων που συμμορφώνονται με το πρωτόκολλο RawRepresentable, το @AppStorage επίσης λειτουργεί αυτόματα. Εάν ένα enum έχει rawValue τύπου String ή Int, μπορεί να χρησιμοποιηθεί απευθείας: @AppStorage("theme") var theme: AppTheme = .system. Το SwiftUI σειριαλοποιεί/αποσειριαλοποιεί αυτόματα την τιμή μέσω rawValue.

swift
enum AppTheme: String {
    case system, light, dark
}

struct SettingsView: View {
    @AppStorage("username") var username: String = "Guest"
    @AppStorage("launchCount") var launchCount: Int = 0
    @AppStorage("isDarkMode") var isDarkMode: Bool = false
    @AppStorage("appTheme") var theme: AppTheme = .system
    @AppStorage("lastOpened") var lastOpened: Date? = nil

    var body: some View {
        Form {
            TextField("Username", text: $username)
            Toggle("Dark mode", isOn: $isDarkMode)
            Text("Εκκινήθηκε \(launchCount) φορές")
        }
    }
}

Στο παράδειγμα χρησιμοποιούνται διαφορετικοί τύποι @AppStorage: String με προκαθορισμένη τιμή «Guest», Int για τον απαριθμητή εκκινήσεων, Bool για το σκοτεινό θέμα, enum AppTheme με rawValue τύπου String και προαιρετικό Date? για την τελευταία φορά ανοίγματος. Κάθε ιδιότητα είναι συνδεδεμένη με ένα κλειδί UserDefaults που καθορίζεται ως πρώτο όρισμα. Η προκαθορισμένη τιμή χρησιμοποιείται εάν το κλειδί δεν υπάρχει στην αποθήκευση κατά την πρώτη εκκίνηση.

Παρακολούθηση αλλαγών Store

Ένα από τα βασικά πλεονεκτήματα του @AppStorage — η αυτόματη παρακολούθηση των αλλαγών UserDefaults από οποιαδήποτε πηγή. Εάν μια App Extension ή Widget αλλάξει μια τιμή, το @AppStorage στη γονική εφαρμογή λαμβάνει ειδοποίηση και ανασχεδιάζει το View. Αυτό επιτυγχάνεται μέσω του μηχανισμού KVO (Key-Value Observing), τον οποίο το @AppStorage ρυθμίζει αυτόματα στο UserDefaults.didChangeNotification.

Στην πράξη, αυτό σημαίνει ότι εάν ο χρήστης αλλάξει μια ρύθμιση στο Widget (π.χ., ενεργοποιήσει το σκοτεινό θέμα), η εφαρμογή παραλαμβάνει αμέσως αυτήν την αλλαγή. Παρομοίως λειτουργεί ο συγχρονισμός μεταξύ της κύριας εφαρμογής και του Share Extension, Watch App ή Today Widget. Ο πραγματοποιητής δεν χρειάζεται να γράψει κώδικα για την διαδικασιακή ανταλλαγή δεδομένων — το @AppStorage το κάνει αυτόματα.

swift
struct ThemeSettingView: View {
    @AppStorage("isDarkMode") var isDarkMode: Bool = false

    var body: some View {
        VStack {
            Toggle("Dark Mode", isOn: $isDarkMode)
                .onChange(of: isDarkMode) { oldValue, newValue in
                    print("Σκοτεινή λειτουργία άλλαξε σε \(newValue)")
                }
        }
    }
}

Το Toggle συνδέεται με το $isDarkMode μέσω @AppStorage. Κατά την εναλλαγή, η τιμή αποθηκεύεται αυτόματα στο UserDefaults υπό το κλειδί «isDarkMode». Ο τροποποιητής .onChange επιτρέπει την εκτέλεση μιας παρενεργής ενέργειας κατά την αλλαγή — για παράδειγμα, αποστολή αναλυτικών ή ενημέρωση του UI άλλων οθονών. Εάν το Widget αλλάξει το ίδιο κλειδί, το @AppStorage θα καλέσει επίσης το onChange, εξασφαλίζοντας τη συνέπεια κατάστασης.

Παραδείγματα κώδικα @AppStorage

Ας δούμε μια πλήρη οθόνη ρυθμίσεων εφαρμογής που χρησιμοποιεί το @AppStorage για την αποθήκευση όλων των ρυθμίσεων. Η φόρμα περιέχει ενότητες με διαφορετικούς τύπους ρυθμίσεων: πεδία κειμένου, διακόπτες, απαριθμητές — όλες οι τιμές αποθηκεύονται αυτόματα στο UserDefaults.

swift
struct AppSettingsView: View {
    @AppStorage("displayName") var displayName = ""
    @AppStorage("notificationsEnabled") var notificationsEnabled = true
    @AppStorage("maxResults") var maxResults = 25
    @AppStorage("selectedTab") var selectedTab = "home"

    var body: some View {
        NavigationStack {
            Form {
                Section(header: Text("Προφίλ")) {
                    TextField("Display name", text: $displayName)
                }

                Section(header: Text("Προτιμήσεις")) {
                    Toggle("Enable notifications",
                           isOn: $notificationsEnabled)
                    Stepper("Max results: \(maxResults)",
                           value: $maxResults,
                           in: 10...100,
                           step: 5)
                }

                Section {
                    Button("Επαναφορά ρυθμίσεων") {
                        UserDefaults.standard.removePersistentDomain(
                            forName: Bundle.main.bundleIdentifier!)
                    }
                    .tint(.red)
                }
            }
            .navigationTitle("Settings")
        }
    }
}

Η φόρμα περιέχει τέσσερις ιδιότητες @AppStorage διαφορετικών τύπων: String για το όνομα, Bool για ειδοποιήσεις, Int για τον αριθμό αποτελεσμάτων και String για την επιλεγμένη καρτέλα. Όλα τα χειριστήρια συνδέονται με τις ιδιότητες μέσω Binding ($displayName, $notificationsEnabled κ.λπ.). Το κουμπί «Reset settings» επαναφέρει όλα τα UserDefaults, διαγράφοντας το domain της εφαρμογής — μετά από αυτό, το @AppStorage επιστρέφει αυτόματα στις προκαθορισμένες τιμές.

Συγχρονισμός @AppStorage με App Group

swift
struct SharedSettingsView: View {
    let sharedDefaults = UserDefaults(suiteName: "group.com.example.app")

    @AppStorage("widgetTheme", store: UserDefaults(suiteName: "group.com.example.app")!)
    var widgetTheme: String = "σύστημα"

    @AppStorage("widgetColor", store: UserDefaults(suiteName: "group.com.example.app")!)
    var widgetColor: String = "μπλε"

    var body: some View {
        Form {
            Picker("Widget theme", selection: $widgetTheme) {
                Text("Σύστημα").tag("system")
                Text("Φωτεινό").tag("φωτεινό")
                Text("Σκοτεινό").tag("σκοτεινό")
            }
            Picker("Accent color", selection: $widgetColor) {
                Text("Μπλε").tag("blue")
                Text("Πράσινο").tag("πράσινο")
                Text("Κόκκινο").tag("κόκκινο")
            }
        }
    }
}

Για App Group (κοινή αποθήκευση μεταξύ εφαρμογής και επεκτάσεων) το @AppStorage δέχεται την παράμετρο store: UserDefaults(suiteName:). Οι τιμές αποθηκεύονται σε ένα κοινό δοχείο προσβάσιμο από την κύρια εφαρμογή, το Widget, το Watch App και άλλες επεκτάσεις της ίδιας ομάδας. Το Widget μπορεί να διαβάσει αυτές τις ρυθμίσεις, και κατά την αλλαγή στην εφαρμογή, το Widget ενημερώνεται αυτόματα μέσω του μηχανισμού παρακολούθησης UserDefaults.

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

Ποια είναι η διαφορά μεταξύ @AppStorage και @State;

Το @State αποθηκεύει την τιμή μόνο στη μνήμη και επαναφέρεται κατά την επανεκκίνηση της εφαρμογής. Το @AppStorage αποθηκεύει την τιμή στο UserDefaults και την επαναφέρει στην επόμενη εκκίνηση. Χρησιμοποιήστε το @State για προσωρινά δεδομένα οθόνης, το @AppStorage — για ρυθμίσεις που πρέπει να επιβιώσουν σε επανεκκίνηση.

Μπορεί να χρησιμοποιηθεί το @AppStorage με Enum;

Ναι, εάν το Enum υλοποιεί το πρωτόκολλο RawRepresentable με rawValue τύπου String ή Int. Παράδειγμα: @AppStorage("theme") var theme: AppTheme = .system. Το SwiftUI σειριαλοποιεί αυτόματα το enum μέσω rawValue και το επαναφέρει κατά τη φόρτωση.

Πώς να εκκαθαρίσω όλες τις τιμές @AppStorage;

Καλέστε UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!) για την τυπική αποθήκευση ή removeObject(forKey:) για ένα συγκεκριμένο κλειδί. Μετά την εκκάθαρση, όλες οι ιδιότητες @AppStorage επιστρέφουν στις προκαθορισμένες τιμές που καθορίζονται στη δήλωση.

Λειτουργεί το @AppStorage με App Extensions;

Ναι, για συγχρονισμό μεταξύ εφαρμογής και επεκτάσεων χρησιμοποιήστε App Group: @AppStorage("key", store: UserDefaults(suiteName: "group.com.example.app")!). Το Widget, Share Extension και Watch App μπορούν να διαβάζουν και να γράφουν στο ίδιο UserDefaults, και οι αλλαγές παρακολουθούνται αυτόματα.

Πόσα δεδομένα μπορούν να αποθηκευτούν στο @AppStorage;

Το @AppStorage χρησιμοποιεί UserDefaults, το οποίο έχει σχεδιαστεί για μικρές ποσότητες δεδομένων: ρυθμίσεις, τοκενια, απαριθμητές. Το συνιστώμενο όριο είναι έως 100 KB ανά εφαρμογή. Για δομημένα ή μεγάλα δεδομένα (πίνακες αντικειμένων, αρχεία πολυμέσων) χρησιμοποιήστε SwiftData, Core Data ή σύστημα αρχείων.

Περίληψη

  • @AppStorage — property wrapper για αντιδραστική αποθήκευση ρυθμίσεων στο UserDefaults
  • Αυτόματη αποθήκευση και αυτόματη ενημέρωση UI κατά την αλλαγή της τιμής από οποιαδήποτε πηγή
  • Υποστηρίζει String, Int, Double, Bool, Data, URL και RawRepresentable enums
  • Προκαθορισμένη τιμή ορίζεται στη δήλωση και επαναφέρεται κατά την πρώτη εκκίνηση
  • App Group επιτρέπει τον συγχρονισμό @AppStorage μεταξύ εφαρμογής και επεκτάσεων
  • UserDefaults είναι κατάλληλο μόνο για μικρές ποσότητες δεδομένων — έως 100 KB
  • Χρησιμοποιήστε @AppStorage για ρυθμίσεις χρήστη, @State — για προσωρινές καταστάσεις οθόνης

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

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

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

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