Az NSUserDefaults egy kulcs-érték adattároló iOS, watchOS, tvOS és macOS rendszeren, amely az alkalmazás beállításainak és konfigurációinak mentésére szolgál. Az adatok egy plist fájlban tárolódnak az alkalmazás homokozójában, és automatikusan szinkronizálódnak az iCloud-dal az NSUbiquitousKeyValueStore segítségével. A hivatalos dokumentáció szerint Apple Developer, 2025, az NSUserDefaults támogatja a primitív típusok tárolását: String, Int, Bool, Float, Double, Data, Date, Array és Dictionary. Az osztály át lett nevezve UserDefaults-ra a Swift 3-tól kezdve, de az Objective-C NSUserDefaults név továbbra is széles körben használatos a kódbázisban és az Apple dokumentációjában.
Főbb pontok
Az NSUserDefaults (UserDefaults Swift-ben) egy beépített Apple mechanizmus kulcs-érték párok plist formátumban történő tárolására. Elérhető minden Apple platformon: iOS, iPadOS, watchOS, tvOS és macOS. Fő cél — felhasználói preferenciák, interfész állapot, első indítás jelzők, kiválasztott opciók és egyéb egyszerű adatok mentése, amelyek túlélik az alkalmazás újraindítását.
Minden iOS alkalmazásnak izolált homokozója van, és az NSUserDefaults a Library/Preferences könyvtárban tárolódik ezen homokozón belül egy Bundle Identifier nevű fájlban. A plist fájl kulcs-érték párokat tartalmaz, ahol a kulcs egy sztring, az érték pedig egy támogatott típus. A fájlméret nem korlátozott, de az Apple csak beállítások tárolását ajánlja a UserDefaults-ban, nem nagy adatmennyiségeket.
iOS 8-tól kezdve az NSUserDefaults támogatja az App Groups-ot — megosztott tárolást ugyanazon fejlesztő alkalmazásai és bővítményei (widgetek, watchOS kísérő alkalmazások) között. Ehhez az init?(suiteName:) inicializátor használatos az App Group azonosítóval. Ez lehetővé teszi például, hogy egy widget a Today képernyőn olvassa a beállításokat a fő alkalmazásból a mentési logika duplikálása nélkül.
Fizikailag az NSUserDefaults egy bináris plist fájlban tárolódik a következő útvonalon: {Sandbox}/Library/Preferences/com.example.myapp.plist. A fájl a bináris plist formátumot (NSPropertyListBinaryFormat_v1_0) használja a tömörség és olvasási sebesség érdekében. macOS-en a fájl XML formátumú lehet a kompatibilitás érdekében. Az Android SharedPreferences-szel ellentétben a UserDefaults plist fájlok beágyazott struktúrákat tartalmazhatnak Dictionary és Array segítségével.
Az NSUserDefaults fájlok alapértelmezetten nem titkosítottak. Az adatok nyílt formában tárolódnak, és fizikai hozzáféréssel az eszközhöz vagy biztonsági másolaton keresztül olvashatók. Érzékeny adatok (jelszavak, tokenek, titkosítási kulcsok) tárolására az Apple határozottan a Keychain használatát ajánlja, amely automatikusan titkosítja az adatokat az operációs rendszer szintjén.
Az NSUserDefaults a memóriában történő gyorsítótárazás elvén működik, időszakos lemezre szinkronizálással. Az első hozzáféréskor a UserDefaults.standard példányhoz a rendszer betölti a plist fájlt a RAM-ba Dictionary formájában. Az összes későbbi olvasás a memóriából történik. Az írás is először a memóriában történik, a lemezre szinkronizálás pedig időszakosan a háttérben zajlik.
Az írási műveletek a set(_:forKey:) metódust használják, amely egy opcionális Any? típusú értéket fogad. Az érték lehet nil — a kulcs eltávolításához. Az azonnali lemezre íráshoz korábban a synchronize() metódust használták, de iOS 7 és OS X 10.9 óta erre már nincs szükség — a rendszer automatikusan szinkronizálja az adatokat rendszeres időközönként. Az Apple hivatalosan is redundánsnak nyilvánította a synchronize()-t a dokumentációjában.
Az NSUserDefaults a regiszterek (tartományok) rendszerét használja az értékek keresésének megszervezésére. Amikor az alkalmazás értéket kér egy kulcs alapján, a UserDefaults egymás után ellenőrzi a tartományokat meghatározott sorrendben: először NSArgumentDomain (parancssori argumentumok), majd az alkalmazás tartománya (Application), aztán NSGlobalDomain (rendszerbeállítások), majd nyelvspecifikus tartományok és végül NSRegistrationDomain (a register(defaults:) segítségével regisztrált alapértékek).
import Foundation
// Standard UserDefaults példány
let defaults = UserDefaults.standard
// Értékek írása
defaults.set("Anna Petrova", forKey: "username")
defaults.set(28, forKey: "age")
defaults.set(true, forKey: "isLoggedIn")
// Alapértékek regisztrálása
defaults.register(defaults: [
"theme": "system",
"fontSize": 14
])
// Olvasás alapérték visszaadásával
let theme = defaults.string(forKey: "theme") ?? "system"
let fontSize = defaults.integer(forKey: "fontSize")
Az NSRegistrationDomain tartomány egy szoftvertartomány, amely csak a RAM-ban létezik és nem kerül mentésre a lemezre. Az alapértékek beállítására szolgál, amelyek addig hatnak, amíg az alkalmazás nem írja saját értékét az alkalmazás tartományába. Ez lehetővé teszi egy egységes alapértelmezett beállítás konfigurációs pont létrehozását, amely központilag módosítható a fejlesztési fázisban.
Az NSUserDefaults egy sor típusos metódust biztosít az adatok olvasásához és írásához: string(forKey:), integer(forKey:), bool(forKey:), float(forKey:), double(forKey:), data(forKey:), array(forKey:), dictionary(forKey:) és object(forKey:). Minden olvasási metódushoz tartozik egy megfelelő set(_:forKey:) írási metódus a tárolt érték típusának automatikus meghatározásával. A Swift verzió szigorú típusosságot használ, de az Objective-C verzió id-t fogad és ad vissza.
| Olvasási metódus (Swift) | Adattípus | Alapérték |
|---|---|---|
| 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 |
A synchronize() metódus az NSUserDefaults-ban kényszeríti az összes változtatás kiírását a memóriából a lemezre. Az iOS korai verzióiban ezt a metódust minden írás után meg kellett hívni az adatok mentésének garantálásához. iOS 7 óta a rendszer automatikusan szinkronizálja a UserDefaults-ot a háttérben, és az Apple hivatalosan is redundánsnak nyilvánította a synchronize()-t. A metódus hívása nem okoz hibát, de nem nyújt semmilyen további mentési garanciát.
A változások figyeléséhez az NSUserDefaults biztosítja az UserDefaults.didChangeNotification értesítést és az addObserver(_:forKeyPath:options:context:) KVO megfigyelési metódust. SwiftUI-ben elérhető a @AppStorage Property Wrapper, amely automatikusan szinkronizálja a UserDefaults értéket az UI frissítéssel. A @AppStorage ugyanazokat a típusokat támogatja mint a UserDefaults, és ez a preferált módja a beállításokkal való munkának SwiftUI alkalmazásokban.
// Változások megfigyelése KVO-n keresztül
class SettingsViewModel: NSObject {
override func observeValue(
forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey: Any]?,
context: UnsafeMutableRawPointer?
) {
guard let keyPath else { return }
print("Kulcs megváltozott: \(keyPath)")
}
}
// SwiftUI - AppStorage
struct SettingsView: View {
@AppStorage("theme") private var theme: String = "system"
var body: some View {
Picker("Téma", selection: $theme) {
Text("Rendszer").tag("system")
Text("Világos").tag("light")
Text("Sötét").tag("dark")
}
}
}
Az App Groups (megosztott tároló az alkalmazás és bővítményei között) használatához a UserDefaults(suiteName:) inicializátor használatos az App Group azonosítóval. Például, "group.com.example.myapp". Az ebbe a példányba írt adatok elérhetők a fő alkalmazásból, widgetből, watchOS kísérő alkalmazásból és más, ugyanazon App Group-hoz tartozó bővítményből. Minden suite példány külön plist fájlban tárolódik.
A kényelem és egyszerűség ellenére az NSUserDefaults nem univerzális tároló minden adattípushoz iOS-en. A mennyiségtől, kritikusságtól és biztonsági követelményektől függően az Apple több alternatívát kínál, amelyek mindegyike egy adott használati forgatókönyvre optimalizált.
| Megoldás | Mikor használjuk | Korlátozások |
|---|---|---|
| NSUserDefaults | Interfész beállítások és konfiguráció | Nem alkalmas nagy adatokhoz és titkokhoz |
| Keychain | Jelszavak, tokenek, titkosítási kulcsok | Bonyolultabb használat, lassabb |
| CoreData | Strukturált adatok kapcsolatokkal | Túlzott 10-20 beállításhoz |
| FileManager | Dokumentumok, képek, bináris adatok | Kézi fájlkezelést igényel |
| CloudKit | Felhő szinkronizálás eszközök között | iCloud fiókot és hálózati kapcsolatot igényel |
A Keychain egy védett Apple tároló bizalmas adatok számára. Az NSUserDefaults-szal ellentétben a Keychain-ben lévő összes adat titkosítva van az operációs rendszer szintjén a Secure Enclave hardveres titkosítás segítségével kompatibilis eszközökön. A Keychain automatikusan zárolódik és feloldódik az eszközzel együtt, és támogatja a hozzáférés megosztását ugyanazon fejlesztő alkalmazásai között a Keychain Access Groups segítségével.
A Keychain fő hátránya az API bonyolultsága. Egy egyszerű sztring mentéséhez létre kell hozni egy SecItemAdd kérést az attribútumok megadásával: osztály (kSecClassGenericPassword), szolgáltatás (kSecAttrService), fiók (kSecAttrAccount) és maga az adat (kSecValueData). A Keychain használatának egyszerűsítésére léteznek harmadik féltől származó burkolók, mint a KeychainAccess és a SwiftKeychainWrapper, amelyek kényelmes kulcs-érték interfészt biztosítanak hasonlóan a UserDefaults-hoz.
Nézzünk egy gyakorlati példát: az onboarding (üdvözlő képernyők) állapotának mentése és visszaállítása egy iOS alkalmazásban az NSUserDefaults segítségével. Az első indításkor a felhasználó látja az onboarding képernyőket, amelyek áthaladása után egy jelző mentésre kerül a UserDefaults-ban. A későbbi indításoknál az onboarding kimarad. SwiftUI esetén a @AppStorage használatos, UIKit esetén — közvetlen hozzáférés a UserDefaults.standard-hoz.
Hozzunk létre egy OnboardingManager menedzsert, amely beágyazza a UserDefaults-szal való munkát az onboarding állapot tárolásához. A menedzser biztosítja az isOnboardingCompleted tulajdonságot az állapot ellenőrzéséhez és a markOnboardingCompleted metódust a jelző beállításához. A tárolási kulcs konstansba van kiemelve a gépelési hibák megelőzése érdekében. Az egységteszteléshez a menedzser a UserDefaultsProtocol protokollt használja, amely lehetővé teszi a valódi tároló MockUserDefaults-szal való helyettesítését.
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)
}
}
// Használat az alkalmazásban
let onboardingManager = OnboardingManager()
if !onboardingManager.isOnboardingCompleted {
showOnboarding()
} else {
showMainScreen()
}
Összetettebb beállítások, például egy strukturált Profile objektum tárolásához a Codable protokoll és JSONEncoder/JSONDecoder használata ajánlott. Az objektum JSONEncoder segítségével Data-vá szerializálódik, set(_:forKey:) segítségével mentődik, és olvasáskor JSONDecoder segítségével deszerializálódik Data-ból vissza objektummá. Ez a megközelítés lehetővé teszi összetett struktúrák tárolását a UserDefaults-ban a típusbiztonság elvesztése nélkül.
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)
}
}
// Használat
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")
Fontos emlékezni, hogy az NSUserDefaults nem nagy adatmennyiségek tárolására készült. Az Apple a tárolt adatok méretének néhány tíz kilobájtra korlátozását ajánlja. Nagy objektumok (képek, dokumentumok, szerializált modellek) tárolásához a FileManager-t a Documents könyvtárral vagy a CoreData-t kell használni. Ezenkívül a UserDefaults nem támogatja az adatséma verziókezelését — a Codable modell szerkezetének megváltozásakor a régi adatok nem deszerializálódhatnak, és ezt az alkalmazás kódjában kell kezelni.
Gyakran Ismételt Kérdések
Mindkettő kulcs-érték tároló, de az NSUserDefaults több típust támogat (Data, Date, Array, Dictionary) és automatikusan szinkronizál az iCloud-dal. A SharedPreferences XML-ben tárol, az NSUserDefaults plist formátumban. Az NSUserDefaults tartományrendszerrel rendelkezik kaszkád kereséssel, a SharedPreferences egyszerű lapos struktúrát használ fájlnevekkel.
Nem, az NSUserDefaults nyílt formában tárolja az adatokat titkosítás nélkül. Jelszavak, tokenek és titkosítási kulcsok esetén használja a Keychain-t, amely titkosítja az adatokat a Secure Enclave szintjén. A Keychain támogatja a hozzáférési attribútumokat, mint a biometrikus hitelesítés (Face ID / Touch ID) a titok olvasása előtt.
Az eszközök közötti szinkronizáláshoz használja az NSUbiquitousKeyValueStore-t — az iCloud felhő kulcs-érték tárolóját. Az egyik eszközön ebbe a szolgáltatásba írt adatok automatikusan megjelennek ugyanazon iCloud fiók összes többi eszközén. Maximális méret — 1 MB alkalmazásonként, 1024 kulcs.
Az összes adat törléséhez hívja meg a removePersistentDomain(forName:) metódust az alkalmazás Bundle Identifier-ével. Egyedi értékek törléséhez használja a removeObject(forKey:) metódust. Az alkalmazás beállításainak teljes visszaállításához: UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!). Minden törlés azonnal érvényesül a memória gyorsítótárban.
Az Apple nem állapít meg szigorú korlátot az NSUserDefaults méretére, de ajánlott nem túllépni a 100 KB-ot az összes tárolt adat teljes mennyiségére vonatkozóan. Nagy mennyiségekhez használja a CoreData-t vagy a FileManager-t. Több mint 1 MB adat tárolásakor az alkalmazás indításakor az olvasási teljesítmény észrevehetően csökkenhet.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is