NSUserDefaults — qu’est-ce que c’est, API UserDefaults et travail avec les réglages iOS

Auteur : IT Sectr Publié le : 2026-03-12 Temps de lecture : 10 min

NSUserDefaults est un stockage de données clé-valeur sous iOS, watchOS, tvOS et macOS, conçu pour sauvegarder les préférences et configurations d’une application. Les données sont stockées dans un fichier plist dans le sandbox de l’application et se synchronisent automatiquement avec iCloud via NSUbiquitousKeyValueStore. Selon la documentation officielle d’Apple Developer, 2025, NSUserDefaults prend en charge le stockage des types primitifs : String, Int, Bool, Float, Double, Data, Date, Array et Dictionary. La classe a été renommée UserDefaults à partir de Swift 3, mais son nom Objective-C NSUserDefaults reste largement utilisé dans les bases de code et la documentation Apple.

Points essentiels

  • NSUserDefaults est un stockage clé-valeur sur iOS et macOS pour sauvegarder les réglages simples d’application dans un fichier plist.
  • Prend en charge neuf types de données : String, Int, Bool, Float, Double, Data, Date, Array et Dictionary.
  • Les données se synchronisent automatiquement avec iCloud via NSUbiquitousKeyValueStore avec le support du développeur.
  • Utilise un système de domaines avec recherche en cascade le long de la chaîne de domaines.
  • Pour stocker des données sensibles, Apple recommande d’utiliser Keychain au lieu de NSUserDefaults.

Qu’est-ce que NSUserDefaults ?

NSUserDefaults (UserDefaults en Swift) est le mécanisme intégré d’Apple pour stocker des paires clé-valeur au format plist. Il est disponible sur toutes les plateformes Apple : iOS, iPadOS, watchOS, tvOS et macOS. Son objectif principal est de sauvegarder les préférences utilisateur, l’état de l’interface, les indicateurs de premier lancement, les options sélectionnées et d’autres données simples qui persistent après les redémarrages de l’application.

Chaque application iOS dispose d’un sandbox isolé, et NSUserDefaults est stocké dans le répertoire Library/Preferences à l’intérieur de ce sandbox dans un fichier portant le nom du Bundle Identifier. Le fichier plist contient des paires clé-valeur où la clé est une chaîne et la valeur est l’un des types pris en charge. La taille du fichier n’est pas limitée, mais Apple recommande de stocker uniquement des réglages dans UserDefaults, et non de grandes quantités de données.

À partir d’iOS 8, NSUserDefaults a commencé à prendre en charge les App Groups — un stockage partagé entre les applications d’un même développeur et leurs extensions (widgets, applications compagnes watchOS). Pour cela, on utilise l’initialisateur init?(suiteName:) avec un identifiant App Group. Cela permet, par exemple, à un widget Today de lire les réglages de l’application principale sans dupliquer la logique de sauvegarde.

Format de stockage : plist sur l’appareil

Physiquement, NSUserDefaults est stocké dans un fichier plist binaire à : {Sandbox}/Library/Preferences/com.example.myapp.plist. Le fichier utilise le format plist binaire (NSPropertyListBinaryFormat_v1_0) pour la compacité et la vitesse de lecture. Sous macOS, le fichier peut être au format XML pour la compatibilité. Contrairement à SharedPreferences sous Android, les fichiers plist de UserDefaults peuvent contenir des structures imbriquées via Dictionary et Array.

Les fichiers NSUserDefaults ne sont pas chiffrés par défaut. Les données sont stockées en texte clair et peuvent être lues avec un accès physique à l’appareil ou via une sauvegarde. Pour stocker des données sensibles (mots de passe, jetons, clés de chiffrement), Apple recommande fortement d’utiliser Keychain, qui chiffre automatiquement les données au niveau du système d’exploitation.

Comment fonctionne NSUserDefaults sous iOS

NSUserDefaults fonctionne sur le principe de mise en cache en mémoire avec une synchronisation périodique sur le disque. Lors du premier accès à l’instance standard UserDefaults.standard, le système charge le fichier plist dans la RAM sous forme de Dictionary. Toutes les lectures suivantes sont effectuées à partir de la mémoire. L’écriture se fait également d’abord en mémoire, la synchronisation sur le disque ayant lieu périodiquement dans un thread d’arrière-plan.

Les opérations d’écriture utilisent la méthode set(_:forKey:), qui accepte une valeur optionnelle de type Any?. La valeur peut être nil — utilisée pour supprimer une clé. Pour une écriture immédiate sur le disque, la méthode synchronize() était utilisée auparavant, mais à partir d’iOS 7 et OS X 10.9, elle n’est plus nécessaire — le système synchronise automatiquement les données à intervalles réguliers. Apple a officiellement déclaré synchronize() redondant dans sa documentation.

Registres UserDefaults et domaines

NSUserDefaults utilise un système de registres (domaines) pour organiser la recherche de valeurs. Lorsqu’une application demande une valeur par clé, UserDefaults vérifie séquentiellement les domaines dans un ordre spécifique : d’abord NSArgumentDomain (arguments de ligne de commande), puis le domaine de l’Application, puis NSGlobalDomain (réglages système), puis les domaines spécifiques à la langue, et enfin NSRegistrationDomain (valeurs par défaut enregistrées via register(defaults:)).

swift
import Foundation

// Instance standard de UserDefaults
let defaults = UserDefaults.standard

// Écriture de valeurs
defaults.set("Anna Petrova", forKey: "username")
defaults.set(28, forKey: "age")
defaults.set(true, forKey: "isLoggedIn")

// Enregistrement des valeurs par défaut
defaults.register(defaults: [
    "theme": "system",
    "fontSize": 14
])

// Lecture avec retour de la valeur par défaut
let theme = defaults.string(forKey: "theme") ?? "system"
let fontSize = defaults.integer(forKey: "fontSize")

Le domaine NSRegistrationDomain est un domaine programmatique qui n’existe qu’en mémoire et n’est pas persisté sur le disque. Il est utilisé pour définir des valeurs par défaut qui s’appliquent jusqu’à ce que l’application écrive sa propre valeur dans le domaine de l’Application. Cela permet de créer un point de configuration unique pour les réglages par défaut qui peuvent être modifiés de manière centralisée pendant le développement.

Méthodes principales de NSUserDefaults

NSUserDefaults fournit un ensemble de méthodes typées pour lire et écrire des données : string(forKey:), integer(forKey:), bool(forKey:), float(forKey:), double(forKey:), data(forKey:), array(forKey:), dictionary(forKey:) et object(forKey:). Chaque méthode de lecture a une méthode d’écriture correspondante set(_:forKey:) avec une détermination automatique du type de la valeur stockée. La version Swift de UserDefaults utilise un typage fort, mais la version Objective-C accepte et retourne id.

Méthode de lecture (Swift)Type de donnéesValeur par défaut
string(forKey:)String?nil
integer(forKey:)Int0
bool(forKey:)Boolfalse
float(forKey:)Float0.0
double(forKey:)Double0.0
data(forKey:)Data?nil

synchronize et sa pertinence

La méthode synchronize() dans NSUserDefaults force l’écriture de toutes les modifications de la mémoire vers le disque. Dans les premières versions d’iOS, cette méthode devait être appelée après chaque écriture pour garantir la persistance des données. À partir d’iOS 7, le système synchronise automatiquement UserDefaults dans un thread d’arrière-plan, et Apple a officiellement déclaré synchronize() redondant. L’appel de cette méthode ne provoque pas d’erreur mais n’offre aucune garantie supplémentaire de persistance.

Pour surveiller les modifications, NSUserDefaults fournit la notification UserDefaults.didChangeNotification et la méthode d’observation KVO addObserver(_:forKeyPath:options:context:). Dans SwiftUI, le Property Wrapper @AppStorage est disponible, qui synchronise automatiquement une valeur dans UserDefaults avec la mise à jour de l’interface utilisateur. @AppStorage prend en charge les mêmes types que UserDefaults et est la méthode préférée pour travailler avec les réglages dans les applications SwiftUI.

swift
// Observation des changements 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("Clé modifiée : \(keyPath)")
    }
}

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

    var body: some View {
        Picker("Thème", selection: $theme) {
            Text("Système").tag("system")
            Text("Clair").tag("light")
            Text("Sombre").tag("dark")
        }
    }
}

Pour travailler avec les App Groups (stockage partagé entre une application et ses extensions), utilisez l’initialisateur UserDefaults(suiteName:) avec un identifiant App Group. Par exemple, «group.com.example.myapp». Les données écrites dans cette instance sont accessibles depuis l’application principale, le widget, l’application compagne watchOS et les autres extensions appartenant au même App Group. Chaque instance suite est stockée dans un fichier plist séparé.

NSUserDefaults vs alternatives de stockage

Malgré sa commodité et sa simplicité, NSUserDefaults n’est pas une solution de stockage universelle pour tous les types de données sur iOS. Selon le volume, la criticité et les exigences de sécurité, Apple fournit plusieurs alternatives, chacune optimisée pour un cas d’utilisation spécifique.

SolutionQuand l’utiliserLimitations
NSUserDefaultsRéglages d’interface et configurationNe convient pas aux grandes données ou secrets
KeychainMots de passe, jetons, clés de chiffrementPlus complexe à utiliser, plus lent
CoreDataDonnées structurées avec relationsExcessif pour 10–20 réglages
FileManagerDocuments, images, données binairesNécessite une gestion manuelle des fichiers
CloudKitSynchronisation cloud entre appareilsNécessite un compte iCloud et une connexion réseau

Keychain — stockage sécurisé

Keychain est le stockage sécurisé d’Apple pour les données confidentielles. Contrairement à NSUserDefaults, toutes les données dans Keychain sont chiffrées au niveau du système d’exploitation en utilisant le chiffrement matériel de Secure Enclave sur les appareils compatibles. Keychain se verrouille et se déverrouille automatiquement avec l’appareil et prend en charge le partage d’accès entre les applications d’un même développeur via Keychain Access Groups.

Le principal inconvénient de Keychain est la complexité de son API. Pour simplement sauvegarder une chaîne, vous devez créer une requête SecItemAdd en spécifiant les attributs : classe (kSecClassGenericPassword), service (kSecAttrService), compte (kSecAttrAccount) et les données réelles (kSecValueData). Pour simplifier le travail avec Keychain, il existe des wrappers tiers tels que KeychainAccess et SwiftKeychainWrapper qui fournissent une interface clé-valeur pratique similaire à UserDefaults.

Exemple d’utilisation de NSUserDefaults en Swift

Considérons un exemple pratique : sauvegarder et restaurer l’état d’onboarding (écrans de bienvenue) dans une application iOS en utilisant NSUserDefaults. Au premier lancement, l’utilisateur voit les écrans d’onboarding ; après les avoir complétés, un indicateur est sauvegardé dans UserDefaults. Lors des lancements suivants, l’onboarding est ignoré. Pour SwiftUI, on utilise @AppStorage ; pour UIKit, un accès direct à UserDefaults.standard.

Sauvegarde de l’état d’onboarding

Créons un OnboardingManager qui encapsule le travail avec UserDefaults pour stocker l’état d’onboarding. Le gestionnaire fournit une propriété isOnboardingCompleted pour vérifier l’état et une méthode markOnboardingCompleted pour définir l’indicateur. La clé de stockage est extraite dans une constante pour éviter les fautes de frappe. Pour les tests unitaires, le gestionnaire utilise un protocole UserDefaultsProtocol, permettant de remplacer le stockage réel par un 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)
    }
}

// Utilisation dans l’application
let onboardingManager = OnboardingManager()
if !onboardingManager.isOnboardingCompleted {
    showOnboarding()
} else {
    showMainScreen()
}

Pour stocker des réglages plus complexes, comme un objet Profile structuré, il est recommandé d’utiliser le protocole Codable et JSONEncoder/JSONDecoder. L’objet est sérialisé en Data via JSONEncoder, sauvegardé via set(_:forKey:), et à la lecture, désérialisé de Data en objet via JSONDecoder. Cette approche permet de stocker des structures complexes dans UserDefaults sans perdre la sécurité de typage.

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

// Utilisation
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")

Il est important de se rappeler que NSUserDefaults n’est pas conçu pour stocker de grandes quantités de données. Apple recommande de limiter les données stockées à quelques dizaines de kilo-octets. Pour stocker des objets volumineux (images, documents, modèles sérialisés), utilisez FileManager avec le répertoire Documents ou CoreData. De plus, UserDefaults ne prend pas en charge le versionnement de schéma de données — lorsque la structure du modèle Codable change, les anciennes données peuvent ne pas se désérialiser, ce qui doit être géré dans le code de l’application.

Foire aux questions

Quelle est la différence entre NSUserDefaults et SharedPreferences sur Android ?

Les deux sont des magasins clé-valeur, mais NSUserDefaults prend en charge plus de types (Data, Date, Array, Dictionary) et se synchronise automatiquement avec iCloud. SharedPreferences stocke les données en XML, NSUserDefaults au format plist. NSUserDefaults possède un système de domaines avec recherche en cascade, tandis que SharedPreferences utilise une structure plate simple avec des noms de fichiers.

Est-il sûr de stocker des mots de passe dans NSUserDefaults ?

Non, NSUserDefaults stocke les données en texte clair sans chiffrement. Pour les mots de passe, jetons et clés de chiffrement, utilisez Keychain, qui chiffre les données au niveau de Secure Enclave. Keychain prend également en charge les attributs d’accès tels que l’authentification biométrique (Face ID / Touch ID) avant la lecture d’un secret.

Comment synchroniser NSUserDefaults entre appareils ?

Pour la synchronisation entre les appareils d’un même utilisateur, utilisez NSUbiquitousKeyValueStore — le stockage clé-valeur cloud iCloud. Les données écrites dans ce service sur un appareil apparaissent automatiquement sur tous les autres appareils avec le même compte iCloud. Capacité maximale : 1 Mo par application, 1024 clés.

Comment supprimer toutes les données de NSUserDefaults ?

Pour supprimer toutes les données, appelez la méthode removePersistentDomain(forName:) avec le Bundle Identifier de l’application. Pour supprimer des valeurs individuelles, utilisez removeObject(forKey:). Pour une réinitialisation complète des réglages : UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!). Toutes les suppressions sont appliquées immédiatement au cache en mémoire.

Quelle est la taille maximale des données dans NSUserDefaults ?

Apple ne fixe pas de limite stricte pour la taille de NSUserDefaults, mais il est recommandé de ne pas dépasser 100 Ko de volume total pour toutes les données stockées. Pour des volumes plus importants, utilisez CoreData ou FileManager. Lors du stockage de plus d’1 Mo de données, les performances de lecture au démarrage de l’application peuvent diminuer sensiblement.

Résumé

  • NSUserDefaults est le stockage clé-valeur intégré d’Apple pour les réglages simples d’application au format plist.
  • Prend en charge neuf types de données : String, Int, Bool, Float, Double, Data, Date, Array et Dictionary.
  • Utilise un système de domaines avec recherche en cascade via NSRegistrationDomain, NSGlobalDomain et le domaine de l’Application.
  • Pour la synchronisation entre appareils Apple, Apple fournit NSUbiquitousKeyValueStore avec une limite de 1 Mo par application.
  • Pour la sécurité, utilisez Keychain pour les mots de passe et jetons, pas NSUserDefaults.
  • Dans SwiftUI, la méthode préférée est le Property Wrapper @AppStorage avec synchronisation automatique de l’interface utilisateur.
  • Pour les données volumineuses ou structurées, choisissez CoreData ou FileManager au lieu de NSUserDefaults.

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi