NSUserDefaults removeObjectForKey vs. setObject: nil

116

Czy poniższe dwa wiersze są równoważne?

1. [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"example key"]

2. [[NSUserDefaults standardUserDefaults] setObject:nil forKey:@"example key"]

ma11hew28
źródło
1
Tak, z wyjątkiem tego, że pierwszy krok sprawia, że ​​twój zamiar jest znacznie bardziej jasny.
BallpointBen

Odpowiedzi:

14

Swift 3.0

Poniższa odpowiedź nie ma już miejsca, kiedy to testowałem. Gdy ustawiony nilna wynik, jest przechowywany NSCFData. Prawdopodobnie odwołanie do obiektu NSNull, ale nie mam pewności.

Aby całkowicie usunąć wartość klucza, użyj UserDefaults.standard.removeObject(forKey: "YourDefault")

Testowałem z następującym kodem:

UserDefaults.standard.set(["a", "b", "c"], forKey: "MyDefaults")
print("Test A: My saved defaults \(UserDefaults.standard.object(forKey: "MyDefaults"))")

UserDefaults.standard.set(nil, forKey: "MyDefaults")
print("Test B: My defaults set to nil \(UserDefaults.standard.object(forKey: "MyDefaults"))")

UserDefaults.standard.removeObject(forKey: "MyDefaults")
print("Test C: My defaults removed \(UserDefaults.standard.object(forKey: "MyDefaults"))")
Sean
źródło
Interesujące, że w Swift, kiedy wpisuję set (nil, forKey: ...) i używam „skoku do definicji”, przenosi mnie do narzędzia ustawiającego adresy URL. W komentarzu tej funkcji jest napisane „-setURL: forKey jest równoważne -setObject: forKey: z tą różnicą, że wartość jest archiwizowana w NSData”. To może wyjaśniać, dlaczego działa źle - ponieważ istnieją dwie przeciążone funkcje, które akceptują nil, Swift musi wybrać jedną, ale setURL nie zachowuje się tak samo.
Richard Venable
96

Tak, oba wiersze kodu są równoważne, oba spowodują zerowy odczyt

id obj = [[NSUserDefaults standardUserDefaults] objectForKey:@"example key"];

NSUserDefaultszwróci nil, jeśli klucz nie został znaleziony. Zalecałbym użycie removeObjectForKeyzamiast ustawiania go na zero.

oto jak sprawdzić, czy ustawienie wartości klucza na zero spowodowało usunięcie wpisu klucza z NSUserDefaults standardUserDefaults.

NSArray *keys = [[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] allKeys] copy];
   for(NSString *key in keys) {
       NSLog(@"Key Name: %@", key);
}
[keys release];

lub po prostu zrzuć słownik kluczy / wartości NSUserDefaults standardUserDefaults

NSLog(@"All contents of NSUserDefaults: %@", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]);
Człowiek rakieta
źródło
Tak, ale jeśli ustawisz to na zero, czy zrobisz to automatycznie removeObjectForKey?
ma11hew28
nie jestem pewien, czy ustawienie go na „nil” spowoduje usunięcie wpisu klucza w [NSUserDefaults standardUserDefaults]. Szybkim testem byłoby pobranie „allKeys” [[NSUserDefaults standardUserDefaults] allKeys] i iteracja przez NSArrya nazw kluczy, sprawdzenie, czy ustawienie klucza na zero powoduje usunięcie klucza z tablicy „allKey”.
RocketMan
9
wynik to „TAK” zarówno „removeObjectForKey”, jak i „setObject: nil” usuwają klucz @ „przykładowy klucz” z [NSUserDefaults standardUserDefaults]
RocketMan
9
dzięki! Potwierdziłem to również. Dla wyjaśnienia, setObject:nilusunie również przedmiot, a nie tylko jego klucz. Zatem obie funkcje powodują dokładnie ten sam wynik. Ponadto, jeśli usuniesz (lub ustawisz na zero) jedyny przechowywany obiekt (i klucz), cały plik .plist zostanie usunięty.
ma11hew28
1

Swift 5.0 + iOS 11 i nowsze

Obie metody usuwają wartość. Próbowałem tego na placu zabaw:

import Foundation

let key = "Test"
let value = "test"
let defaults = UserDefaults.standard

func printUD() {
    print("UserDefaults after modification:\n")
    defaults.dictionaryRepresentation().forEach { print("\($0): \($1)\n") }
    print("-------------\n\n")
}

defaults.set(value, forKey: key); printUD()
defaults.set(nil, forKey: key); printUD()
defaults.set(value, forKey: key); printUD()
defaults.removeObject(forKey: key); printUD()

W wersjach starszych niż iOS 11 spowoduje to serializację nildo Datai zgłoszenie błędu.

Daniil Korotin
źródło