Usuwanie NSUserDefaults

Odpowiedzi:

514

Możesz usunąć trwałą domenę aplikacji w następujący sposób:

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

W Swift 3 i nowszych:

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

Jest to podobne do odpowiedzi @samvermette, ale jest trochę czystsze IMO.

Christopher Rogers
źródło
Działa świetnie, dzięki! Tylko nie zapomnij później wydać appDomain.
IcyBlueRose
15
@IcyBlueRose - bundleIdentifier to obiekt automatycznie wydany, ponieważ nie zaczyna się on od init ani nowego, więc można go nadmiernie wydać.
Christopher Rogers
1
Dobrze wiedzieć, dziękuję! Ale mówiłem o aplikacji strunowej Domena. Czy to także auto wydane?
IcyBlueRose
2
@IcyBlueRose Obiekt zwrócony przez bundleIdentifier jest taki sam jak obiekt, do którego odwołuje się appDomain.
Christopher Rogers
2
Wydaje mi się, że nie mogę już tego uruchomić w wersji 10.8. Czy ktoś mógłby potwierdzić, że to działa? Oto powiązane pytanie SO: stackoverflow.com/questions/13595415/…
DaGaMs,
102

Ten kod resetuje wartości domyślne do domeny rejestracji:

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

Innymi słowy, removeObjectForKeydla każdego klucza zarejestrowanego w tej aplikacji.

Podziękowania dla Kena Thomasesa w tym wątku na forach programistów Apple .

samvermette
źródło
4
Wielkie dzięki. Dlaczego [NSUserDefaults resetStandardUserDefaults]tego nie zrobię, to przede mną.
jakeboxer
2
@ jboxer Właśnie spędziłem trochę czasu studiując dokumentację Apple i resetStandardUserDefaults w zasadzie opróżnia bufor w pamięci na dysk i czyści go. Więc następnym razem, gdy spróbujesz odzyskać wartość, musi ona pobrać ją z dysku. NSManagedObjectContext w Core Data używa również podobnej terminologii „reset”.
Christopher Rogers
2
Ups, chodziło mi o to, że czyści bufor w pamięci bez zapisywania go na dysku. Tak więc wszelkie zmiany dokonane przed synchronizacją z dyskiem zostaną utracone.
Christopher Rogers
4
Christopher, myślę, że masz to wstecz, choć może coś się zmieniło. resetStandardUserDefaults to najbardziej myląca nazwa połączenia, jakie widziałem do tej pory w iOS. Dokumenty Apple mówią: „Synchronizuje wszelkie zmiany wprowadzone w domyślnym obiekcie współdzielonego użytkownika i zwalnia go z pamięci”. dlatego tak naprawdę powinno się nazywać flushAndReleaseStandardUserDefaults. Poświęcam czas na komentowanie starego komentarza, ponieważ właśnie złapałem się na tym połączeniu i chcę uniknąć poparzenia innych (muszę teraz powiedzieć klientowi, że muszę zaktualizować 90 aplikacji).
Andy Dent
97

Próbowałeś użyć - removeObjectForKey?

 [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"defunctPreference"];
sbooth
źródło
Pozdrawiam. Bardzo ceniony.
TonyNeallon,
5
Jakiś sposób, aby usunąć obiekt dla wszystkich istniejących kluczy?
samvermette,
2
Rozumiem, że wydaje się, że to działa, dlaczego nie jest nieistotna Preferencja jakiegoś rodzaju stałej systemowej? Z pewnością byłbym zdenerwowany, że któregoś dnia przestanie działać.
David H
Czy musisz później zsynchronizować?
Travis M.,
30

Oto odpowiedź w Swift:

let appDomain = NSBundle.mainBundle().bundleIdentifier!
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(appDomain)
juliensaad
źródło
8
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(NSBundle.mainBundle().bundleIdentifier!)one-liner
Grace Shao
3
Lub bezpieczniej:if let domainName = NSBundle.mainBundle().bundleIdentifier { NSUserDefaults.standardUserDefaults().removePersistentDomainForName(domainName) }
Valentin Shergin
1
Swift 4 wersja oneliner Grace:UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)
Carsten Hagemann
28

Jeśli potrzebujesz go podczas programowania, możesz również zresetować symulator, usuwając wszystkie NSUserDefaults.

Symulator iOS -> Resetuj zawartość i ustawienia ...

Pamiętaj, że spowoduje to również usunięcie wszystkich aplikacji i plików z symulatora.

Roger Sanoli
źródło
15
NSDictionary *defaultsDictionary = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
for (NSString *key in [defaultsDictionary allKeys]) {
                    [[NSUserDefaults standardUserDefaults] removeObjectForKey:key];
}
folse
źródło
7

W Swift:

let defaults = NSUserDefaults.standardUserDefaults()
defaults.dictionaryRepresentation().keys.forEach { defaults.removeObjectForKey($0) }
Adam Waite
źródło
6

Uwaga: Ta odpowiedź została również zaktualizowana dla Swift.

Co powiesz na to, aby mieć go w jednej linii?

Rozszerzenie odpowiedzi na @Christopher Rogers - zaakceptowana.

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

i tak, czasami może być to synchronizekonieczne,

[[NSUserDefaults standardUserDefaults] synchronize];

Stworzyłem metodę, aby to zrobić,

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

Szybki ?

Dzięki swift jest jeszcze łatwiejszy.

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

I użycie :

UserDefaults.clean()
Hemang
źródło
6

Uwielbiam rozszerzenia, gdy czynią kod czystszym:

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

        self.removePersistentDomainForName(domainName)
    }
}

Szybki 5

extension UserDefaults {
    func clear() {
        guard let domainName = Bundle.main.bundleIdentifier else {
            return
        }
        removePersistentDomain(forName: domainName)
        synchronize()
    }
}
Valentin Shergin
źródło
5

Znalazłem to:

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 "{}"

Źródło: https://gist.github.com/ZevEisenberg/5a172662cb576872d1ab

Daniel Gomez Rico
źródło
2

Wszystkie powyższe odpowiedzi są bardzo trafne, ale jeśli ktoś nadal nie może zresetować domyślnych ustawień użytkownika dla usuniętej aplikacji, możesz zresetować ustawienia zawartości swojego symulatora, i to zadziała.wprowadź opis zdjęcia tutaj

iDevAmit
źródło
2

Jest to błąd lub cokolwiek innego, ale removePersistentDomainForNamenie działa podczas usuwania wszystkich NSUserDefaultswartości.

Lepszą opcją jest zresetowanie PersistentDomaini można to zrobić w następujący sposób:

NSUserDefaults.standardUserDefaults().setPersistentDomain(["":""], forName: NSBundle.mainBundle().bundleIdentifier!)
Sohil R. Memon
źródło
1

Rozwijając odpowiedź @ folse ... Wierzę, że poprawniejsze wdrożenie byłoby ...

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];
    }

... wywołanie metody persistentDomainForName: NSUserDefault. Zgodnie ze stanem dokumentacji metoda „Zwraca słownik zawierający klucze i wartości w określonej trwałej domenie”. Wywołanie słownika Reprezentacja: zamiast tego zwróci słownik, który prawdopodobnie będzie zawierał inne ustawienia, ponieważ dotyczy szerszego zakresu.

Jeśli musisz odfiltrować dowolną z wartości, które mają zostać zresetowane, możesz to zrobić iteracyjnie po klawiszach. Oczywiście, jeśli chcesz po prostu zrezygnować z wszystkich prefiksów aplikacji, bez względu na to, jedna z pozostałych metod wymienionych powyżej jest najbardziej wydajna.

Markeissler
źródło
0

Spróbuj tego, działa dla mnie.

Pojedyncza linia kodu

[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
Jaywant Khedkar
źródło