NSUserDefaults ist ein Schlüssel-Wert-Datenspeicher in iOS, watchOS, tvOS und macOS, der zum Speichern von Anwendungseinstellungen und Konfigurationen entwickelt wurde. Die Daten werden in einer plist-Datei in der Sandbox der Anwendung gespeichert und automatisch über NSUbiquitousKeyValueStore mit iCloud synchronisiert. Laut offizieller Dokumentation von Apple Developer, 2025 unterstützt NSUserDefaults das Speichern primitiver Typen: String, Int, Bool, Float, Double, Data, Date, Array und Dictionary. Die Klasse wurde ab Swift 3 in UserDefaults umbenannt, aber ihr Objective-C-Name NSUserDefaults bleibt in Codebasen und der Apple-Dokumentation weit verbreitet.
Wichtige Punkte
NSUserDefaults (UserDefaults in Swift) ist Apples integrierter Mechanismus zum Speichern von Schlüssel-Wert-Paaren im plist-Format. Es ist auf allen Apple-Plattformen verfügbar: iOS, iPadOS, watchOS, tvOS und macOS. Der Hauptzweck ist das Speichern von Benutzereinstellungen, Oberflächenzuständen, First-Launch-Flags, ausgewählten Optionen und anderen einfachen Daten, die über Neustarts der Anwendung hinaus bestehen bleiben.
Jede iOS-Anwendung hat eine isolierte Sandbox, und NSUserDefaults wird im Verzeichnis Library/Preferences innerhalb dieser Sandbox in einer Datei mit dem Namen der Bundle-ID gespeichert. Die plist-Datei enthält Schlüssel-Wert-Paare, wobei der Schlüssel ein String ist und der Wert einer der unterstützten Typen. Die Dateigröße ist nicht begrenzt, aber Apple empfiehlt, in UserDefaults nur Einstellungen zu speichern, keine großen Datenmengen.
Ab iOS 8 unterstützt NSUserDefaults App Groups — gemeinsamen Speicher zwischen Anwendungen desselben Entwicklers und ihren Erweiterungen (Widgets, watchOS Companion-Apps). Dazu wird der Initialisierer init?(suiteName:) mit einer App-Group-ID verwendet. Dies ermöglicht beispielsweise einem Today-Widget, Einstellungen aus der Hauptanwendung zu lesen, ohne die Speicherlogik zu duplizieren.
Physikalisch wird NSUserDefaults in einer binären plist-Datei gespeichert unter: {Sandbox}/Library/Preferences/com.example.myapp.plist. Die Datei verwendet das binäre plist-Format (NSPropertyListBinaryFormat_v1_0) für Kompaktheit und Lesegeschwindigkeit. Unter macOS kann die Datei aus Kompatibilitätsgründen im XML-Format vorliegen. Im Gegensatz zu SharedPreferences unter Android können UserDefaults-plist-Dateien verschachtelte Strukturen über Dictionary und Array enthalten.
NSUserDefaults-Dateien werden standardmäßig nicht verschlüsselt. Daten werden im Klartext gespeichert und können bei physischem Zugriff auf das Gerät oder über ein Backup gelesen werden. Zum Speichern sensibler Daten (Passwörter, Tokens, Verschlüsselungsschlüssel) empfiehlt Apple dringend die Verwendung von Keychain, das Daten automatisch auf Betriebssystemebene verschlüsselt.
NSUserDefaults arbeitet nach dem Prinzip der Speicher-Caching mit periodischer Datenträger-Synchronisation. Beim ersten Zugriff auf die Standardinstanz UserDefaults.standard lädt das System die plist-Datei als Dictionary in den Arbeitsspeicher. Alle nachfolgenden Lesevorgänge erfolgen aus dem Speicher. Schreibvorgänge erfolgen ebenfalls zuerst im Speicher, während die Festplattensynchronisation periodisch im Hintergrundthread erfolgt.
Schreiboperationen verwenden die Methode set(_:forKey:), die einen optionalen Wert vom Typ Any? akzeptiert. Der Wert kann nil sein — zum Entfernen eines Schlüssels. Für sofortige Schreibvorgänge auf die Festplatte wurde früher die Methode synchronize() verwendet, aber ab iOS 7 und OS X 10.9 ist sie nicht mehr erforderlich — das System synchronisiert Daten automatisch in regelmäßigen Abständen. Apple hat synchronize() in seiner Dokumentation offiziell für überflüssig erklärt.
NSUserDefaults verwendet ein System von Registern (Domänen) zur Organisation der Wertesuche. Wenn eine Anwendung einen Wert per Schlüssel anfordert, überprüft UserDefaults nacheinander die Domänen in einer bestimmten Reihenfolge: zuerst NSArgumentDomain (Kommandozeilenargumente), dann die Anwendungsdomäne, dann NSGlobalDomain (Systemeinstellungen), dann sprachspezifische Domänen und schließlich NSRegistrationDomain (über register(defaults:) registrierte Standardwerte).
import Foundation
// Standardinstanz von UserDefaults
let defaults = UserDefaults.standard
// Werte schreiben
defaults.set("Anna Petrowa", forKey: "username")
defaults.set(28, forKey: "age")
defaults.set(true, forKey: "isLoggedIn")
// Standardwerte registrieren
defaults.register(defaults: [
"theme": "system",
"fontSize": 14
])
// Lesen mit Rückgabe des Standardwerts
let theme = defaults.string(forKey: "theme") ?? "system"
let fontSize = defaults.integer(forKey: "fontSize")
Die NSRegistrationDomain ist eine programmatische Domäne, die nur im Speicher existiert und nicht auf die Festplatte geschrieben wird. Sie wird verwendet, um Standardwerte festzulegen, die gelten, bis die Anwendung ihren eigenen Wert in die Anwendungsdomäne schreibt. Dies ermöglicht die Erstellung eines einzigen Konfigurationspunkts für Standardeinstellungen, die während der Entwicklung zentral geändert werden können.
NSUserDefaults bietet eine Reihe von typisierten Methoden zum Lesen und Schreiben von Daten: string(forKey:), integer(forKey:), bool(forKey:), float(forKey:), double(forKey:), data(forKey:), array(forKey:), dictionary(forKey:) und object(forKey:). Jede Lesemethode hat eine entsprechende Schreibmethode set(_:forKey:) mit automatischer Typerkennung des gespeicherten Werts. Die Swift-Version von UserDefaults verwendet starke Typisierung, während die Objective-C-Version id akzeptiert und zurückgibt.
| Lesemethode (Swift) | Datentyp | Standardwert |
|---|---|---|
| string(forKey:) | String? | nil |
| integer(forKey:) | Int | 0 |
| bool(forKey:) | Bool | false |
| float(forKey:) | Float | 0.0 |
| double(forKey:) | Double | 0.0 |
| data(forKey:) | Data? | nil |
Die Methode synchronize() in NSUserDefaults erzwingt das Schreiben aller Änderungen aus dem Speicher auf die Festplatte. In früheren iOS-Versionen musste diese Methode nach jedem Schreibvorgang aufgerufen werden, um die Datenpersistenz zu gewährleisten. Ab iOS 7 synchronisiert das System UserDefaults automatisch im Hintergrundthread, und Apple hat synchronize() offiziell für überflüssig erklärt. Der Aufruf dieser Methode verursacht keinen Fehler, bietet aber keine zusätzlichen Persistenzgarantien.
Zur Überwachung von Änderungen bietet NSUserDefaults die Benachrichtigung UserDefaults.didChangeNotification und die KVO-Beobachtungsmethode addObserver(_:forKeyPath:options:context:). In SwiftUI steht der Property Wrapper @AppStorage zur Verfügung, der einen Wert in UserDefaults automatisch mit UI-Updates synchronisiert. @AppStorage unterstützt dieselben Typen wie UserDefaults und ist die bevorzugte Methode zum Arbeiten mit Einstellungen in SwiftUI-Anwendungen.
// Änderungsbeobachtung via KVO
class SettingsViewModel: NSObject {
override func observeValue(
forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey: Any]?,
context: UnsafeMutableRawPointer?
) {
guard let keyPath else { return }
print("Schlüssel geändert: \(keyPath)")
}
}
// SwiftUI - AppStorage
struct SettingsView: View {
@AppStorage("theme") private var theme: String = "system"
var body: some View {
Picker("Thema", selection: $theme) {
Text("System").tag("system")
Text("Hell").tag("light")
Text("Dunkel").tag("dark")
}
}
}
Für die Arbeit mit App Groups (gemeinsamer Speicher zwischen einer Anwendung und ihren Erweiterungen) verwenden Sie den Initialisierer UserDefaults(suiteName:) mit einer App-Group-ID. Zum Beispiel „group.com.example.myapp“. Daten, die in diese Instanz geschrieben werden, sind von der Hauptanwendung, dem Widget, der watchOS Companion-App und anderen Erweiterungen derselben App Group zugänglich. Jede Suite-Instanz wird in einer separaten plist-Datei gespeichert.
Trotz seiner Bequemlichkeit und Einfachheit ist NSUserDefaults keine universelle Speicherlösung für alle Datentypen unter iOS. Abhängig von Umfang, Kritikalität und Sicherheitsanforderungen bietet Apple mehrere Alternativen, die jeweils für einen bestimmten Anwendungsfall optimiert sind.
| Lösung | Wann verwenden | Einschränkungen |
|---|---|---|
| NSUserDefaults | Oberflächeneinstellungen und Konfiguration | Nicht geeignet für große Datenmengen oder Geheimnisse |
| Keychain | Passwörter, Tokens, Verschlüsselungsschlüssel | Komplexer in der Anwendung, langsamer |
| CoreData | Strukturierte Daten mit Beziehungen | Überdimensioniert für 10–20 Einstellungen |
| FileManager | Dokumente, Bilder, Binärdaten | Erfordert manuelle Dateiverwaltung |
| CloudKit | Cloud-Synchronisation zwischen Geräten | Erfordert iCloud-Konto und Netzwerkverbindung |
Keychain ist Apples sicherer Speicher für vertrauliche Daten. Im Gegensatz zu NSUserDefaults werden alle Daten in der Keychain auf Betriebssystemebene mit Hardwareverschlüsselung der Secure Enclave auf kompatiblen Geräten verschlüsselt. Die Keychain sperrt und entsperrt automatisch mit dem Gerät und unterstützt die gemeinsame Nutzung des Zugriffs zwischen Anwendungen desselben Entwicklers über Keychain Access Groups.
Der Hauptnachteil der Keychain ist die Komplexität der API. Um nur einen String zu speichern, müssen Sie eine SecItemAdd-Abfrage mit Angabe von Attributen erstellen: Klasse (kSecClassGenericPassword), Dienst (kSecAttrService), Konto (kSecAttrAccount) und die eigentlichen Daten (kSecValueData). Zur Vereinfachung der Arbeit mit der Keychain gibt es Drittanbieter-Wrapper wie KeychainAccess und SwiftKeychainWrapper, die eine bequeme Schlüssel-Wert-Schnittstelle ähnlich wie UserDefaults bieten.
Betrachten wir ein praktisches Beispiel: Speichern und Wiederherstellen des Onboarding-Status (Begrüßungsbildschirme) in einer iOS-Anwendung mit NSUserDefaults. Beim ersten Start sieht der Benutzer die Onboarding-Bildschirme; nach Abschluss wird ein Flag in UserDefaults gespeichert. Bei späteren Starts wird das Onboarding übersprungen. Für SwiftUI wird @AppStorage verwendet; für UIKit direkter Zugriff auf UserDefaults.standard.
Erstellen wir einen OnboardingManager, der die Arbeit mit UserDefaults zum Speichern des Onboarding-Status kapselt. Der Manager bietet eine Eigenschaft isOnboardingCompleted zum Überprüfen des Status und eine Methode markOnboardingCompleted zum Setzen des Flags. Der Speicherschlüssel wird in eine Konstante extrahiert, um Tippfehler zu vermeiden. Für Unit-Tests verwendet der Manager ein UserDefaultsProtocol, das es ermöglicht, den tatsächlichen Speicher durch einen MockUserDefaults zu ersetzen.
class OnboardingManager {
private let defaults: UserDefaults
private let hasSeenKey = "has_seen_onboarding"
init(defaults: UserDefaults = .standard) {
self.defaults = defaults
}
var isOnboardingCompleted: Bool {
defaults.bool(forKey: hasSeenKey)
}
func markOnboardingCompleted() {
defaults.set(true, forKey: hasSeenKey)
}
func resetOnboarding() {
defaults.removeObject(forKey: hasSeenKey)
}
}
// Verwendung in der Anwendung
let onboardingManager = OnboardingManager()
if !onboardingManager.isOnboardingCompleted {
showOnboarding()
} else {
showMainScreen()
}
Zum Speichern komplexerer Einstellungen, wie eines strukturierten Profile-Objekts, wird die Verwendung des Codable-Protokolls und von JSONEncoder/JSONDecoder empfohlen. Das Objekt wird über JSONEncoder in Data serialisiert, über set(_:forKey:) gespeichert und beim Lesen über JSONDecoder aus Data zurück in das Objekt deserialisiert. Dieser Ansatz ermöglicht das Speichern komplexer Strukturen in UserDefaults ohne Verlust der Typsicherheit.
struct UserProfile: Codable {
let name: String
let age: Int
let preferences: [String: String]
}
extension UserDefaults {
func save<T: Codable>(_ value: T, forKey key: String) {
if let data = try? JSONEncoder().encode(value) {
set(data, forKey: key)
}
}
func load<T: Codable>(_ type: T.Type, forKey key: String) -> T? {
guard let data = data(forKey: key) else { return nil }
return try? JSONDecoder().decode(type, from: data)
}
}
// Verwendung
let profile = UserProfile(name: "Anna", age: 28, preferences: ["theme": "dark"])
UserDefaults.standard.save(profile, forKey: "user_profile")
let loaded = UserDefaults.standard.load(UserProfile.self, forKey: "user_profile")
Es ist wichtig zu bedenken, dass NSUserDefaults nicht für die Speicherung großer Datenmengen ausgelegt ist. Apple empfiehlt, die gespeicherten Daten auf einige Dutzend Kilobyte zu beschränken. Zum Speichern großer Objekte (Bilder, Dokumente, serialisierte Modelle) verwenden Sie FileManager mit dem Documents-Verzeichnis oder CoreData. Darüber hinaus unterstützt UserDefaults keine Datenbankschemataversionsverwaltung — wenn sich die Codable-Modellstruktur ändert, können alte Daten möglicherweise nicht deserialisiert werden, und dies muss im Anwendungscode behandelt werden.
Häufig gestellte Fragen
Beide sind Schlüssel-Wert-Speicher, aber NSUserDefaults unterstützt mehr Typen (Data, Date, Array, Dictionary) und synchronisiert automatisch mit iCloud. SharedPreferences speichert Daten in XML, NSUserDefaults im plist-Format. NSUserDefaults hat ein Domänensystem mit kaskadierender Suche, während SharedPreferences eine einfache flache Struktur mit Dateinamen verwendet.
Nein, NSUserDefaults speichert Daten unverschlüsselt im Klartext. Für Passwörter, Tokens und Verschlüsselungsschlüssel verwenden Sie Keychain, das Daten auf Secure-Enclave-Ebene verschlüsselt. Die Keychain unterstützt auch Zugriffsattribute wie biometrische Authentifizierung (Face ID / Touch ID) vor dem Lesen eines Geheimnisses.
Zur Synchronisation zwischen Geräten desselben Benutzers verwenden Sie NSUbiquitousKeyValueStore — den iCloud-Schlüssel-Wert-Cloud-Speicher. Daten, die auf einem Gerät in diesen Dienst geschrieben werden, erscheinen automatisch auf allen anderen Geräten mit derselben iCloud-ID. Maximale Kapazität: 1 MB pro Anwendung, 1024 Schlüssel.
Um alle Daten zu löschen, rufen Sie die Methode removePersistentDomain(forName:) mit der Bundle-ID der Anwendung auf. Zum Entfernen einzelner Werte verwenden Sie removeObject(forKey:). Für einen vollständigen Einstellungsreset: UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!). Alle Löschungen werden sofort auf den In-Memory-Cache angewendet.
Apple setzt keine strenge Grenze für die Größe von NSUserDefaults, es wird jedoch empfohlen, 100 KB Gesamtvolumen aller gespeicherten Daten nicht zu überschreiten. Für größere Volumen verwenden Sie CoreData oder FileManager. Bei mehr als 1 MB gespeicherter Daten kann die Leseleistung beim Starten der Anwendung merklich nachlassen.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.