Suppression de NSUserDefaults

Réponses:

514

Vous pouvez supprimer le domaine persistant de l'application comme ceci:

NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];

Dans Swift 3 et versions ultérieures:

if let bundleID = Bundle.main.bundleIdentifier {
    UserDefaults.standard.removePersistentDomain(forName: bundleID)
}

Ceci est similaire à la réponse de @samvermette mais est un peu plus propre OMI.

Christopher Rogers
la source
Cela a très bien fonctionné, merci! N'oubliez pas de libérer appDomain par la suite.
IcyBlueRose
15
@IcyBlueRose - bundleIdentifier est un objet libéré automatiquement car il ne commence pas par init ou new, vous devriez donc le sur-relâcher.
Christopher Rogers
1
Bon à savoir, merci! Mais je parlais de la chaîne appDomain. Est-ce que cette voiture est également sortie?
IcyBlueRose
2
@IcyBlueRose L'objet renvoyé par bundleIdentifier est le même que l'objet référencé par appDomain.
Christopher Rogers
2
Je n'arrive plus à faire fonctionner cela sur 10.8, est-ce que quelqu'un pourrait confirmer que cela fonctionne? Voici une question SO connexe: stackoverflow.com/questions/13595415/…
DaGaMs
102

Ce code réinitialise les valeurs par défaut au domaine d'enregistrement:

[[NSUserDefaults standardUserDefaults] setPersistentDomain:[NSDictionary dictionary] forName:[[NSBundle mainBundle] bundleIdentifier]];

En d'autres termes, cela removeObjectForKeypour chaque clé que vous avez déjà enregistrée dans cette application.

Crédits à Ken Thomases sur ce fil de discussion des développeurs Apple .

samvermette
la source
4
Merci beaucoup. Pourquoi [NSUserDefaults resetStandardUserDefaults]ne fait pas cela me dépasse.
jakeboxer
2
@jboxer Je viens de passer un peu de temps à étudier la documentation Apple et resetStandardUserDefaults vide essentiellement le tampon en mémoire sur le disque et l'efface. Donc, la prochaine fois que vous essayez de récupérer une valeur, il doit la récupérer sur le disque. NSManagedObjectContext de Core Data utilise également une terminologie de «réinitialisation» similaire.
Christopher Rogers
2
Oups, je voulais dire qu'il efface le tampon en mémoire sans l'écrire sur le disque. Ainsi, toutes les modifications apportées avant la synchronisation sur le disque seront perdues.
Christopher Rogers
4
Christopher, je pense que tu l'as à l'envers bien que les choses aient peut-être changé. resetStandardUserDefaults est l'appel le plus déroutant que j'ai vu jusqu'à présent dans iOS. Les Apple Docs disent "Synchronise toutes les modifications apportées à l'objet par défaut de l'utilisateur partagé et le libère de la mémoire." il faut donc vraiment l'appeler flushAndReleaseStandardUserDefaults. Je prends le temps de commenter un ancien commentaire parce que je viens de me faire prendre par cet appel et que je veux éviter que quelqu'un d'autre ne soit brûlé (je dois maintenant dire à un client que je dois mettre à jour 90 applications).
Andy Dent
97

Avez-vous essayé d'utiliser - removeObjectForKey?

 [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"defunctPreference"];
sbooth
la source
Bravo sbooth. Très appréciée.
TonyNeallon
5
Est-il possible de supprimer un objet pour toutes les clés existantes?
samvermette du
2
Bien que je comprenne que cela semble fonctionner, pourquoi defunctPreference n'est-il pas une sorte de système défini constant? Je serais certainement nerveux que cela cesserait de fonctionner un jour à l'avenir.
David H
Devez-vous synchroniser après?
Travis M.
30

Voici la réponse dans Swift:

let appDomain = NSBundle.mainBundle().bundleIdentifier!
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(appDomain)
juliensaad
la source
8
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(NSBundle.mainBundle().bundleIdentifier!)one-liner
Grace Shao
3
Ou plus sûr:if let domainName = NSBundle.mainBundle().bundleIdentifier { NSUserDefaults.standardUserDefaults().removePersistentDomainForName(domainName) }
Valentin Shergin
1
Version Swift 4 de la doublure de Grace:UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)
Carsten Hagemann
28

Si vous en avez besoin lors du développement, vous pouvez également réinitialiser votre simulateur, en supprimant tous les NSUserDefaults.

iOS Simulator -> Réinitialiser le contenu et les paramètres ...

Gardez à l'esprit qu'il supprimera également toutes les applications et tous les fichiers du simulateur.

Roger Sanoli
la source
15
NSDictionary *defaultsDictionary = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
for (NSString *key in [defaultsDictionary allKeys]) {
                    [[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
}
folse
la source
7

Dans Swift:

let defaults = NSUserDefaults.standardUserDefaults()
defaults.dictionaryRepresentation().keys.forEach { defaults.removeObjectForKey($0) }
Adam Waite
la source
6

Remarque: Cette réponse a également été mise à jour pour Swift.

Qu'en est-il de l'avoir sur une seule ligne?

Étendre la réponse de @Christopher Rogers - celle qui est acceptée.

[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];

et oui, parfois vous en aurez besoin synchronize,

[[NSUserDefaults standardUserDefaults] synchronize];

J'ai créé une méthode pour ce faire,

- (void) clearDefaults {
    [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
    [[NSUserDefaults standardUserDefaults] synchronize];
}

Rapide ?

Avec rapide, c'est encore plus facile.

extension UserDefaults {
    class func clean() {
        guard let aValidIdentifier = Bundle.main.bundleIdentifier else { return }
        standard.removePersistentDomain(forName: aValidIdentifier)
        standard.synchronize()
    }
}

Et l'utilisation :

UserDefaults.clean()
Hemang
la source
6

J'adore les extensions quand elles rendent le code plus propre:

extension NSUserDefaults {
    func clear() {
        guard let domainName = NSBundle.mainBundle().bundleIdentifier else {
            return
        }

        self.removePersistentDomainForName(domainName)
    }
}

Swift 5

extension UserDefaults {
    func clear() {
        guard let domainName = Bundle.main.bundleIdentifier else {
            return
        }
        removePersistentDomain(forName: domainName)
        synchronize()
    }
}
Valentin Shergin
la source
5

J'ai trouvé ça:

osascript -e 'tell application "iOS Simulator" to quit'
xcrun simctl list devices | grep -v '^[-=]' | cut -d "(" -f2 | cut -d ")" -f1 | xargs -I {} xcrun simctl erase "{}"

Source: https://gist.github.com/ZevEisenberg/5a172662cb576872d1ab

Daniel Gomez Rico
la source
2

Toutes les réponses ci-dessus sont très pertinentes, mais si quelqu'un ne peut toujours pas réinitialiser les paramètres utilisateur pour l'application supprimée, vous pouvez réinitialiser les paramètres de contenu de votre simulateur, et cela fonctionnera.entrez la description de l'image ici

iDevAmit
la source
2

C'est un bug ou autre mais le removePersistentDomainForNamene fonctionne pas en effaçant toutes les NSUserDefaultsvaleurs.

Donc, la meilleure option est de réinitialiser le PersistentDomainet que vous pouvez faire de la manière suivante:

NSUserDefaults.standardUserDefaults().setPersistentDomain(["":""], forName: NSBundle.mainBundle().bundleIdentifier!)
Sohil R. Memon
la source
1

Développer la réponse de @ folse ... Je pense qu'une mise en œuvre plus correcte serait ...

NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
NSDictionary *defaultsDictionary = [[NSUserDefaults standardUserDefaults] persistentDomainForName: appDomain];
    for (NSString *key in [defaultsDictionary allKeys]) {
      NSLog(@"removing user pref for %@", key);
      [[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
    }

... appel de la méthode persistentDomainForName: de NSUserDefault. Comme l'indique la documentation, la méthode "Renvoie un dictionnaire contenant les clés et les valeurs dans le domaine persistant spécifié". Appel à dictionaryRepresentation: renvoie un dictionnaire qui inclura probablement d'autres paramètres, car il s'applique à une portée plus large.

Si vous devez filtrer l'une des valeurs à réinitialiser, alors itérer sur les clés est le moyen de le faire. De toute évidence, si vous souhaitez simplement supprimer toutes les préférences de l'application sans égard, l'une des autres méthodes publiées ci-dessus est la plus efficace.

markeissler
la source
0

si le paramètre d'application à réinitialiser est nsuserdefault pour l'accès au microphone (mon cas), une solution simple est la réponse d'Anthony McCormick ( Iphone - Comment activer l'accès des applications aux médias sur le périphérique? - ALAssetsLibraryErrorDomain Code = -3312 "Accès global refusé" ).

sur l'appareil, accédez à Paramètres> Général> Réinitialiser> Réinitialiser les avertissements de localisation

tmr
la source
0

Essayez ça, ça marche pour moi.

Une seule ligne de code

[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
Jaywant Khedkar
la source