NSUserDefaults removeObjectForKey frente a setObject: nulo

116

¿Son equivalentes las siguientes dos líneas?

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

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

ma11hew28
fuente
1
Sí, excepto que el primero deja mucho más clara su intención.
BallpointBen

Respuestas:

14

Swift 3.0

La respuesta a continuación ya no es el caso cuando probé esto. Cuando se establece en nilel resultado, se almacena NSCFData. Posiblemente una referencia de objeto NSNull, pero no estoy seguro.

Para eliminar completamente un valor para el uso de una clave UserDefaults.standard.removeObject(forKey: "YourDefault")

Probé con el siguiente código:

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
fuente
Interesante, en Swift, cuando escribo set (nil, forKey: ...), y uso "saltar a la definición", me lleva al creador de URL. El comentario de esa función dice "-setURL: forKey es equivalente a -setObject: forKey: excepto que el valor se archiva en un NSData". Esto podría explicar por qué se está comportando mal: dado que hay dos funciones sobrecargadas que aceptan nil, Swift tiene que elegir una, pero setURL no se comporta igual.
Richard Venable
96

Sí, ambas líneas de código son equivalentes, ambas resultarán en lectura nula

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

NSUserDefaultsdevolverá nil si no se encontró la clave. Recomendaría usar el en removeObjectForKeylugar de establecerlo en cero.

aquí se explica cómo probar si establecer el valor de la clave en cero eliminó la entrada de la clave NSUserDefaults standardUserDefaults.

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

o simplemente volcar el diccionario clave / valor de NSUserDefaults standardUserDefaults

NSLog(@"All contents of NSUserDefaults: %@", [[NSUserDefaults standardUserDefaults] dictionaryRepresentation]);
RocketMan
fuente
Sí, pero si lo configura en cero, ¿lo hace automáticamente removeObjectForKey?
ma11hew28
No estoy seguro de si establecerlo en 'nil' eliminará la entrada clave en [NSUserDefaults standardUserDefaults]. Una prueba rápida sería obtener 'allKeys' [[NSUserDefaults standardUserDefaults] allKeys] e iterar a través del NSArrya de los nombres de las claves, averiguar si establecer una clave en nil quita la clave de la matriz 'allKey'.
RocketMan
9
el resultado es 'YES' tanto 'removeObjectForKey' como 'setObject: nil' eliminarán la clave @ "clave de ejemplo" de [NSUserDefaults standardUserDefaults]
RocketMan
9
¡Gracias! Confirmé esto también. Solo para aclarar, setObject:niltambién eliminará el objeto, no solo su clave. Entonces, ambas funciones causan exactamente el mismo resultado. Además, si elimina (o establece en cero) el único objeto almacenado (y clave), se elimina todo el archivo .plist.
ma11hew28
1

Swift 5.0 + iOS 11 y posteriores

Ambos métodos eliminan el valor. Probé esto en un patio de recreo:

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

Antes de IOS 11 este se traducirá en la serialización nilen Datay lanzar un error.

Daniil Korotin
fuente