NSUserDefaults — ce este, UserDefaults API și lucrul cu setările iOS

Autor: IT Sectr Publicat: 2026-03-12 Timp de citire: 10 min

NSUserDefaults este un stoc de date cheie-valoare în iOS, watchOS, tvOS și macOS, destinat salvării setărilor și configurațiilor aplicației. Datele sunt stocate într-un fișier plist în sandbox-ul aplicației și se sincronizează automat cu iCloud prin NSUbiquitousKeyValueStore. Conform documentației oficiale Apple Developer, 2025, NSUserDefaults suportă stocarea tipurilor primitive: String, Int, Bool, Float, Double, Data, Date, Array și Dictionary. Clasa a fost redenumită în UserDefaults începând cu Swift 3, dar numele său Objective-C NSUserDefaults rămâne larg utilizat în baza de cod și documentația Apple.

Puncte principale

  • NSUserDefaults — stocare cheie-valoare pe iOS și macOS pentru salvarea setărilor simple ale aplicației într-un fișier plist.
  • Suportă nouă tipuri de date: String, Int, Bool, Float, Double, Data, Date, Array și Dictionary.
  • Datele se sincronizează automat cu iCloud prin NSUbiquitousKeyValueStore cu suportul dezvoltatorului.
  • Folosește sistemul de registre (domenii) cu căutare în cascadă a valorii pe lanțul de domenii.
  • Pentru stocarea datelor sensibile, Apple recomandă utilizarea Keychain în loc de NSUserDefaults.

Ce este NSUserDefaults?

NSUserDefaults (UserDefaults în Swift) este un mecanism încorporat Apple pentru stocarea perechilor cheie-valoare în format plist. Este disponibil pe toate platformele Apple: iOS, iPadOS, watchOS, tvOS și macOS. Scopul principal — salvarea preferințelor utilizatorului, stării interfeței, flag-urilor de first-launch, opțiunilor selectate și a altor date simple care supraviețuiesc repornirii aplicației.

Fiecare aplicație iOS are un sandbox izolat, iar NSUserDefaults este stocat în directorul Library/Preferences în interiorul acestui sandbox într-un fișier cu numele Bundle Identifier. Fișierul plist conține perechi cheie-valoare, unde cheia este un șir de caractere, iar valoarea este unul dintre tipurile suportate. Dimensiunea fișierului nu este limitată, dar Apple recomandă stocarea doar a setărilor în UserDefaults, nu a unor volume mari de date.

Începând cu iOS 8, NSUserDefaults suportă App Groups — stocare partajată între aplicațiile aceluiași dezvoltator și extensiile lor (widgeturi, aplicații companion watchOS). Pentru aceasta se utilizează inițializatorul init?(suiteName:) cu identificatorul App Group. Acest lucru permite, de exemplu, unui widget de pe ecranul Today să citească setări din aplicația principală fără a duplica logica de salvare.

Format de stocare: plist pe dispozitiv

Fizic, NSUserDefaults este stocat într-un fișier plist binar la calea: {Sandbox}/Library/Preferences/com.example.myapp.plist. Fișierul folosește formatul binar plist (NSPropertyListBinaryFormat_v1_0) pentru compactitate și viteză de citire. Pe macOS, fișierul poate fi în format XML pentru compatibilitate. Spre deosebire de SharedPreferences pe Android, fișierele plist UserDefaults pot conține structuri imbricate prin Dictionary și Array.

Fișierele NSUserDefaults nu sunt criptate implicit. Datele sunt stocate în formă deschisă și pot fi citite cu acces fizic la dispozitiv sau prin backup. Pentru stocarea datelor sensibile (parole, tokenuri, chei de criptare), Apple recomandă categoric utilizarea Keychain, care criptează automat datele la nivelul sistemului de operare.

Cum funcționează NSUserDefaults în iOS

NSUserDefaults funcționează pe principiul cache-ului în memorie cu sincronizare periodică pe disc. La prima accesare a instanței standard UserDefaults.standard, sistemul încarcă fișierul plist în memoria RAM sub formă de Dictionary. Toate citirile ulterioare se fac din memorie. Scrierea are loc, de asemenea, mai întâi în memorie, iar sincronizarea pe disc are loc periodic în fundal.

Operațiile de scriere folosesc metoda set(_:forKey:), care acceptă o valoare de tip opțional Any?. Valoarea poate fi nil — pentru ștergerea cheii. Pentru scrierea imediată pe disc se folosea anterior metoda synchronize(), dar începând cu iOS 7 și OS X 10.9 nu mai este necesară — sistemul sincronizează automat datele la intervale regulate. Apple a declarat oficial synchronize() ca fiind redundantă în documentația sa.

Registrele UserDefaults și domeniile

NSUserDefaults folosește un sistem de registre (domenii) pentru organizarea căutării valorilor. Când aplicația solicită o valoare după cheie, UserDefaults verifică succesiv domeniile într-o ordine specifică: mai întâi NSArgumentDomain (argumente din linia de comandă), apoi domeniul aplicației (Application), apoi NSGlobalDomain (setări sistem), apoi domeniile specifice limbii și în final NSRegistrationDomain (valorile implicite înregistrate prin register(defaults:)).

swift
import Foundation

// Instanța standard UserDefaults
let defaults = UserDefaults.standard

// Scrierea valorilor
defaults.set("Ana Petrova", forKey: "username")
defaults.set(28, forKey: "age")
defaults.set(true, forKey: "isLoggedIn")

// Înregistrarea valorilor implicite
defaults.register(defaults: [
    "theme": "system",
    "fontSize": 14
])

// Citirea cu returnarea valorii implicite
let theme = defaults.string(forKey: "theme") ?? "system"
let fontSize = defaults.integer(forKey: "fontSize")

Domeniul NSRegistrationDomain este un domeniu software care există doar în memoria RAM și nu este salvat pe disc. Este utilizat pentru a stabili valori implicite care sunt active până când aplicația își scrie propria valoare în domeniul aplicației. Acest lucru permite crearea unui punct unic de configurare a setărilor implicite care pot fi modificate centralizat în faza de dezvoltare.

Metodele principale ale NSUserDefaults

NSUserDefaults oferă un set de metode tipizate pentru citirea și scrierea datelor: string(forKey:), integer(forKey:), bool(forKey:), float(forKey:), double(forKey:), data(forKey:), array(forKey:), dictionary(forKey:) și object(forKey:). Fiecare metodă de citire are o metodă de scriere corespunzătoare set(_:forKey:) cu determinare automată a tipului valorii stocate. Versiunea Swift a UserDefaults utilizează tipizare strictă, dar versiunea Objective-C acceptă și returnează id.

Metodă de citire (Swift)Tip de dateValoare implicită
string(forKey:)String?nil
integer(forKey:)Int0
bool(forKey:)Boolfalse
float(forKey:)Float0.0
double(forKey:)Double0.0
data(forKey:)Data?nil

synchronize și actualitatea sa

Metoda synchronize() în NSUserDefaults forțează scrierea tuturor modificărilor din memorie pe disc. În versiunile timpurii de iOS, această metodă trebuia apelată după fiecare scriere pentru garantarea salvării datelor. Începând cu iOS 7, sistemul sincronizează automat UserDefaults în fundal, iar Apple a declarat oficial synchronize() ca fiind redundantă. Apelarea acestei metode nu provoacă o eroare, dar nu oferă nicio garanție suplimentară de salvare.

Pentru monitorizarea modificărilor, NSUserDefaults oferă notificarea UserDefaults.didChangeNotification și metoda de observare KVO addObserver(_:forKeyPath:options:context:). În SwiftUI este disponibil Property Wrapper @AppStorage, care sincronizează automat valoarea din UserDefaults cu actualizarea UI. @AppStorage suportă aceleași tipuri ca UserDefaults și este modalitatea preferată de lucru cu setările în aplicațiile SwiftUI.

swift
// Observarea modificărilor prin KVO
class SettingsViewModel: NSObject {
    override func observeValue(
        forKeyPath keyPath: String?,
        of object: Any?,
        change: [NSKeyValueChangeKey: Any]?,
        context: UnsafeMutableRawPointer?
    ) {
        guard let keyPath else { return }
        print("Cheia s-a schimbat: \(keyPath)")
    }
}

// SwiftUI - AppStorage
struct SettingsView: View {
    @AppStorage("theme") private var theme: String = "system"

    var body: some View {
        Picker("Temă", selection: $theme) {
            Text("Sistem").tag("system")
            Text("Luminoasă").tag("light")
            Text("Întunecată").tag("dark")
        }
    }
}

Pentru lucrul cu App Groups (stocare partajată între aplicație și extensii) se utilizează inițializatorul UserDefaults(suiteName:) cu identificatorul App Group. De exemplu, "group.com.example.myapp". Datele scrise în această instanță sunt accesibile din aplicația principală, widget, aplicația companion watchOS și alte extensii aparținând aceluiași App Group. Fiecare instanță suite este stocată într-un fișier plist separat.

NSUserDefaults vs alternative de stocare

În ciuda confortului și simplității, NSUserDefaults nu este un stoc universal pentru toate tipurile de date pe iOS. În funcție de volum, criticitate și cerințe de securitate, Apple oferă mai multe alternative, fiecare optimizată pentru un scenariu specific de utilizare.

SoluțieCând să utilizațiLimitări
NSUserDefaultsSetări interfață și configurareNu este potrivit pentru date mari și secrete
KeychainParole, tokenuri, chei de criptareMai complex de utilizat, mai lent
CoreDataDate structurate cu relațiiExcesiv pentru 10-20 de setări
FileManagerDocumente, imagini, date binareNecesită gestionare manuală a fișierelor
CloudKitSincronizare în cloud între dispozitiveNecesită cont iCloud și conexiune de rețea

Keychain — stocare securizată

Keychain este un stoc protejat Apple pentru date confidențiale. Spre deosebire de NSUserDefaults, toate datele din Keychain sunt criptate la nivelul sistemului de operare utilizând criptarea hardware Secure Enclave pe dispozitivele compatibile. Keychain se blochează și deblochează automat odată cu dispozitivul și suportă partajarea accesului între aplicațiile aceluiași dezvoltator prin Keychain Access Groups.

Principalul dezavantaj al Keychain este complexitatea API-ului. Pentru a salva simplu un șir de caractere, trebuie creată o cerere SecItemAdd cu specificarea atributelor: clasă (kSecClassGenericPassword), serviciu (kSecAttrService), cont (kSecAttrAccount) și datele propriu-zise (kSecValueData). Pentru simplificarea lucrului cu Keychain există împachetări terțe, precum KeychainAccess și SwiftKeychainWrapper, care oferă o interfață convenabilă cheie-valoare similară cu UserDefaults.

Exemplu de utilizare NSUserDefaults în Swift

Să analizăm un exemplu practic: salvarea și restaurarea stării de onboarding (ecrane de bun venit) într-o aplicație iOS utilizând NSUserDefaults. La prima lansare, utilizatorul vede ecranele de onboarding, după parcurgerea cărora un flag este salvat în UserDefaults. La lansările ulterioare, onboarding-ul este sărit. Pentru SwiftUI se folosește @AppStorage, pentru UIKit — acces direct la UserDefaults.standard.

Salvarea stării de onboarding

Să creăm un manager OnboardingManager care încapsulează lucrul cu UserDefaults pentru stocarea stării de onboarding. Managerul oferă proprietatea isOnboardingCompleted pentru verificarea stării și metoda markOnboardingCompleted pentru setarea flag-ului. Cheia de stocare este extrasă într-o constantă pentru prevenirea greșelilor de tastare. Pentru testare unitară, managerul folosește protocolul UserDefaultsProtocol, care permite înlocuirea depozitului real cu MockUserDefaults.

swift
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)
    }
}

// Utilizare în aplicație
let onboardingManager = OnboardingManager()
if !onboardingManager.isOnboardingCompleted {
    showOnboarding()
} else {
    showMainScreen()
}

Pentru stocarea setărilor mai complexe, precum un obiect structurat Profile, se recomandă utilizarea protocolului Codable și JSONEncoder/JSONDecoder. Obiectul este serializat în Data prin JSONEncoder, salvat prin set(_:forKey:), iar la citire este deserializat din Data înapoi în obiect prin JSONDecoder. Această abordare permite stocarea structurilor complexe în UserDefaults fără pierderea siguranței tipurilor.

swift
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)
    }
}

// Utilizare
let profile = UserProfile(name: "Ana", age: 28, preferences: ["theme": "dark"])
UserDefaults.standard.save(profile, forKey: "user_profile")
let loaded = UserDefaults.standard.load(UserProfile.self, forKey: "user_profile")

Este important de reținut că NSUserDefaults nu este destinat stocării volumelor mari de date. Apple recomandă limitarea dimensiunii datelor stocate la câteva zeci de kilobytes. Pentru stocarea obiectelor mari (imagini, documente, modele serializate) trebuie utilizat FileManager cu directorul Documents sau CoreData. În plus, UserDefaults nu suportă versionarea schemei de date — la modificarea structurii modelului Codable, datele vechi pot să nu se deserializeze, iar acest lucru trebuie gestionat în codul aplicației.

Întrebări frecvente

Cu ce se deosebește NSUserDefaults de SharedPreferences pe Android?

Ambele sunt depozite cheie-valoare, dar NSUserDefaults suportă mai multe tipuri (Data, Date, Array, Dictionary) și se sincronizează automat cu iCloud. SharedPreferences stochează datele în XML, NSUserDefaults — în format plist. NSUserDefaults are un sistem de domenii cu căutare în cascadă, SharedPreferences folosește o structură plată simplă cu nume de fișiere.

Este sigur să stochez parole în NSUserDefaults?

Nu, NSUserDefaults stochează datele în formă deschisă fără criptare. Pentru parole, tokenuri și chei de criptare utilizați Keychain, care criptează datele la nivelul Secure Enclave. Keychain suportă, de asemenea, atribute de acces precum autentificarea biometrică (Face ID / Touch ID) înainte de citirea secretului.

Cum sincronizez NSUserDefaults între dispozitive?

Pentru sincronizarea între dispozitivele aceluiași utilizator utilizați NSUbiquitousKeyValueStore — depozitul cloud cheie-valoare iCloud. Datele scrise în acest serviciu pe un dispozitiv apar automat pe toate celelalte dispozitive ale aceluiași cont iCloud. Volum maxim — 1 MB per aplicație, 1024 chei.

Cum șterg toate datele din NSUserDefaults?

Pentru ștergerea tuturor datelor, apelați metoda removePersistentDomain(forName:) cu Bundle Identifier al aplicației. Pentru ștergerea valorilor individuale utilizați removeObject(forKey:). Pentru resetarea completă a setărilor aplicației: UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!). Toate ștergerile se aplică imediat cache-ului din memorie.

Care este dimensiunea maximă a datelor în NSUserDefaults?

Apple nu stabilește o limită strictă pentru dimensiunea NSUserDefaults, dar se recomandă să nu depășiți 100 KB pentru volumul total al tuturor datelor stocate. Pentru volume mari utilizați CoreData sau FileManager. La stocarea a peste 1 MB de date, performanța de citire la pornirea aplicației poate scădea considerabil.

Rezumat

  • NSUserDefaults — depozitul intern cheie-valoare Apple pentru setări simple ale aplicației în format plist.
  • Suportă nouă tipuri de date: String, Int, Bool, Float, Double, Data, Date, Array și Dictionary.
  • Folosește sistemul de domenii cu căutare în cascadă prin NSRegistrationDomain, NSGlobalDomain și domeniul aplicației.
  • Pentru sincronizarea între dispozitive, Apple oferă NSUbiquitousKeyValueStore cu o limită de 1 MB per aplicație.
  • Pentru securitate, utilizați Keychain pentru parole și tokenuri, nu NSUserDefaults.
  • În SwiftUI, modalitatea preferată de lucru este Property Wrapper @AppStorage cu sincronizare automată UI.
  • Pentru date mari sau structurate, alegeți CoreData sau FileManager în loc de NSUserDefaults.

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și