Löschen Sie alle Schlüssel aus einem NSUserDefaults-Wörterbuch iOS


71

Ich verwende das NSUserDefaults-Wörterbuch, um grundlegende Informationen wie Highscores usw. zu speichern, damit beim Schließen des Benutzers die App-Daten nicht verloren gehen. Sowieso benutze ich:

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];

Daten speichern. Wenn ich zum Beispiel einen neuen Highscore speichern möchte, würde ich Folgendes tun:

[prefs setInteger:1023 forKey:@"highScore"];
[prefs synchronize];  //this is needed in case the app is closed. 

und später, wenn ich den Highscore abrufen möchte, würde ich tun:

[prefs integerForKey:@"highScore"];

sowieso der Punkt ist , dass ich eine Menge anderer Dinge speichern , weil die NSUserDefaults enableSie speichern booleans, integers, objectsusw. , welche Methode würde ich alle Schlüssel ausführen müssen , um zu löschen , so dass NSUserDefaults wie die Faust Zeit wird ich die App starten?

Ich suche so etwas wie:

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs deleteAllKeysAndObjectsInTheDictionary];

oder vielleicht gibt es eine Möglichkeit, alle Schlüssel zu erhalten, und ich muss jedes Objekt durchlaufen, aber ich weiß nicht, wie ich sie entfernen soll.

BEARBEITEN:

Ich habe versucht :

NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[NSUserDefaults resetStandardUserDefaults];
[prefs synchronize];

und ich bin immer noch in der Lage, eine hohe Punktzahl abzurufen ....


Siehe diese verwandte Frage: Löschen Sie alle meine NSUserDefaults, die mit einem bestimmten Wort beginnen , und geben Sie eine gute Antwort zur Verwendung eines NSPredicate , um bestimmte Einträge in NSUserDefaults zu finden.
Basil Bourque

Antworten:


146

Wenn Sie sich die Dokumentation zu NSUserDefaults ansehen, sehen Sie eine Methode - (NSDictionary *) dictionaryRepresentation. Mit dieser Methode können Sie in den Standardbenutzerstandards eine Liste aller Schlüssel in den Benutzerstandards abrufen. Sie können dies dann verwenden, um die Benutzerstandards zu löschen:

- (void)resetDefaults {
    NSUserDefaults * defs = [NSUserDefaults standardUserDefaults];
    NSDictionary * dict = [defs dictionaryRepresentation];
    for (id key in dict) {
        [defs removeObjectForKey:key];
    }
    [defs synchronize];
}

19
Der kürzeste Weg, dies mit den gleichen Ergebnissen zu tun:______________________________________________ NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier]; __________________ [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
Skywinder

10
Dies ist nicht der beste Weg, da es iteriert und versucht, alle Benutzerstandardschlüssel einschließlich der Systemschlüssel zu entfernen , anstatt nur die App-Schlüssel. Die Verwendung von -removePersistentDomainForName: Wie in der anderen Antwort vorgeschlagen, ist viel besser.
Pol

1
Wäre es nicht sinnvoller, [dict removeAllObjects] zu verwenden, anstatt das gesamte Wörterbuch zu durchlaufen?
Fitter Man

@FitterMan nein, das entfernt nur Objekte aus dem Wörterbuch, nicht aus NSUserDefaults...
mxcl

71

Der kürzeste Weg, dies mit den gleichen Ergebnissen wie in Alex Nichols Top-Antwort zu tun :

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

1
So löschen Sie die Zuweisung von NSUserDefaults] initWithSuiteName.
Durgaprasad

1
Vergessen synchronizeSie nicht gleich danach Ihre NSUserDefaults, wenn Sie die Standardeinstellungen so verwenden, dass dies erforderlich ist.
Albert Renshaw

Beachten Sie, dass KVO-Beobachter beim Entfernen einer vollständigen Domain nicht benachrichtigt werden (obwohl eine Benachrichtigung veröffentlicht wird). Aus Gründen der KVO-Kompatibilität ist es wahrscheinlich besser, jeden zurückgegebenen Schlüssel zu durchlaufen persistentDomainForNameund ihn mit zu entfernen removeObjectForKey.
Weil

44

Einzeiler:

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

Vergessen synchronizeSie nicht gleich danach Ihre NSUserDefaults, wenn Sie die Standardeinstellungen so verwenden, dass dies erforderlich ist.
Albert Renshaw

3
Ab iOS 11 ist die Synchronisierung veraltet.
John Fricker

29

Einfache Lösung

Ziel c:

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

Swift 3.0 bis Swift 5.0:

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

16

Schnelle Version:

if let bid = NSBundle.mainBundle().bundleIdentifier {
    NSUserDefaults.standardUserDefaults().removePersistentDomainForName(bid)
}   

1
optional nicht ausgepackt, hält sich nicht an Swift Best Practices
Juan Boero

1
Ja, obwohl die Bundle-ID wahrscheinlich nicht Null ist, wenn Sie das Haupt-Bundle verwenden, wird empfohlen, Juans Code zu verwenden.
Superarts.org

16

+ (void) resetStandardUserDefaultsDie Änderungen werden nicht beibehalten, sondern lediglich das Standardobjekt des In-Memory-Benutzers zurückgesetzt, sodass der nächste synchronizeAufruf von der Kopie auf der Festplatte gelesen wird, anstatt vorhandene In-Memory-Werte mit den On-Disk-Versionen zu überschreiben.

Das Iterieren über die Tasten ist besser, aber es gibt tatsächlich eine Funktion, die dies für Sie erledigt : removePersistentDomainForName:.

// you can usually get the domain via [[NSBundle mainBundle] bundleIdentifier]
[[NSUserDefaults standardUserDefaults]
 removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
// or use a string for any other settings domains you use
//[[NSUserDefaults standardUserDefaults]
// removePersistentDomainForName:@"com.mycompany.myappname"];
[[NSUserDefaults standardUserDefaults] synchronize];

Am Ende des synchronizeVorgangs enthalten sowohl die Festplatten- als auch die Speicherkopien der Benutzerstandards keinen der von Ihrer Anwendung festgelegten Werte.


11

Oneliner in Swift:

Swift 3

NSUserDefaults.standardUserDefaults().removePersistentDomainForName(
NSBundle.mainBundle().bundleIdentifier!)

Swift 4

UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)

Swift 4.0 ----- UserDefaults.standard.removePersistentDomain (forName: Bundle.main.bundleIdentifier!) UserDefaults.standard.synchronize ()
uplearnedu.com

@GerardGrundy Du brauchst nicht .synchronize(). Das machst du nie in so normalen Situationen. Inhalte werden automatisch gespeichert.
Eric Aya

@Moritz Wenn die App heruntergefahren werden muss, bevor sie automatisch gespeichert werden kann, müssen Sie das Speichern erzwingen.
uplearnedu.com

Auch synchronizeist nicht nur "speichern". synchronizespeichert und lädt das gesamte Standardobjekt (das größer als erwartet sein kann). Es ist niemals notwendig aufzurufen synchronize, um die Standardeinstellungen zu "speichern". Wenn Sie es nennen, müssen Sie einen guten Grund haben, und diese sind selten. ;)
Eric Aya

10

Verwenden Sie dies für diejenigen unter Ihnen, die dies im Testziel tun möchten (da dies in removePersistentDomaindiesem Fall nicht funktioniert).

Swift 3:

for key in Array(UserDefaults.standard.dictionaryRepresentation().keys) {
     UserDefaults.standard.removeObject(forKey: key)
}

Beste Lösung, wenn Sie nicht vom Hauptpaket abhängig sein möchten. In meinem Fall habe ich ein bestimmtes Bundle geladen und war mir nicht sicher, ob die Schlüssel wirklich entfernt wurden.
Javier Calatrava Llavería

5

Für Swift 3:

let appDomain = Bundle.main.bundleIdentifier!
UserDefaults.standard.removePersistentDomain(forName: appDomain)

5

Für Swift 3:

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

2

Schnell

 func resetUserDefaults(){

    let userDefaults = NSUserDefaults.standardUserDefaults()
    let dict = userDefaults.dictionaryRepresentation() as NSDictionary

    for key in dict.allKeys {

            userDefaults.removeObjectForKey(key as! String)
    }

    userDefaults.synchronize()

}

2

Schneller
Platz in Ihrer Logik

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

1

Tut diese Methode das nicht:

+ (void)resetStandardUserDefaults

Aus der Dokumentation für NSUserDefaults:

resetStandardUserDefaults

Synchronisiert alle Änderungen, die am Standardobjekt des freigegebenen Benutzers vorgenommen wurden, und gibt es aus dem Speicher frei.

+ (void)resetStandardUserDefaults

Diskussion

Durch einen nachfolgenden Aufruf von standardUserDefaults wird ein neues freigegebenes Benutzerstandardobjekt mit der Standardsuchliste erstellt.

Auf dieser Grundlage können Sie Folgendes tun:

[NSUserDefaults resetStandardUserDefaults];
[NSUserDefaults standardUserDefaults];

und jetzt sollten die Standardeinstellungen zurückgesetzt werden.


wenn ich [NSUserDefaults resetStandardUserDefaults] aufrufe; es löscht nichts.
Tono Nam

Nach meinem Verständnis bezieht sich dies eher auf das freigegebene Objekt standardUserDefaults als auf die auf der Festplatte gespeicherten Informationen, was bedeutet, dass dies keine spürbaren Auswirkungen auf die gespeicherten Benutzerstandards hat.
Alex Nichol

1
@Tono: Wenn Sie anrufen [NSUserDefaults resetStandardUserDefaults];und dann tun NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];, ist mein Verständnis (was möglicherweise falsch ist), dass prefses wieder eine leere Tafel sein wird.
PengOne

@ Alex: Ja, das ist die gleiche Idee. Ich hatte Ihre Antwort noch nicht gelesen, da ich über meine diskutiert hatte. Ich werde die Bearbeitung entfernen und Ihnen diesen Ansatz aufschieben.
PengOne

1

Swift 3 oder 4 Wir können das beschriebene Snippet sogar in diesem modernen Ausdruck vereinfachen:

func clearAll() {
    let settingsDictionary = userDefaults.dictionaryRepresentation()
    settingsDictionary.forEach { key, _ in userDefaults.removeObject(forKey: key) }
    userDefaults.synchronize()
}

0

So entfernen Sie alle UserDefault-Werte in Swift (neueste Syntax)

//remove UserDefaults
  if let identifier = Bundle.main.bundleIdentifier {
      UserDefaults.standard.removePersistentDomain(forName: identifier)
      UserDefaults.standard.synchronize()
  }

0

Ich fand es am praktischsten, den Code in einer Erweiterung zu platzieren UserDefaults.

Swift 5

extension UserDefaults {
    static func clear() {
        guard let domain = Bundle.main.bundleIdentifier else { return }
        UserDefaults.standard.removePersistentDomain(forName: domain)
        UserDefaults.standard.synchronize()
    }
}

Verwendung

UserDefaults.clear()
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.