2011-03-22 16 views
31

Usando NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];,iPhone - Cómo detectar si existe una clave en NSUserDefaults standardUserDefaults

lo uso como llamadas BOOL boolFromPrefs = [defaults boolForKey:@"theBoolKey"]; Para obtener un valor BOOL salvado.

Si no se encuentra la clave, se devuelve NO (comportamiento predeterminado de boolForKey).
Pero ... NO puede ser una configuración guardada. Lo mismo para intForKey

Entonces, ¿cómo puedo probar si una clave existe antes de tratar de obtener su valor?

Respuesta

61

Hazlo de la manera correcta y register default values.

NSDictionary *userDefaultsDefaults = @{ 
    @"SomeKey": @NO, 
    @"AnotherKey": @"FooBar", 
    @"NumberKey": @0, 
}; 
[NSUserDefaults.standardUserDefaults registerDefaults:userDefaultsDefaults]; 

Haga esto antes de usar cualquier cosa desde NSUserDefaults. El comienzo de application:didFinishLaunchingWithOptions: es un lugar seguro.

Debes registrar los valores predeterminados cada vez que se inicia la aplicación. NSUserDefaults solo almacena valores que se han establecido explícitamente.

Si usa los valores predeterminados, no tiene que utilizar una marca para la tecla "isFirstLaunch", como se sugiere en otras respuestas.
Esto lo ayudará cuando despliegue una actualización y desee cambiar el valor predeterminado para un artículo NSUserDefaults.

+1

Veo eso como una opción valiosa pero también puedo ver cómo no registrar los valores predeterminados puede ser beneficioso también. Le da lógica ternaria donde puede saber si el usuario lo estableció explícitamente en sí o no o no lo configuró todo. – Joe

+0

No estoy seguro, pero creo que esta forma de hacerlo funciona bien para la primera versión 1.0. Si tiene un gran cambio en la jerarquía de sus preferencias más adelante, probablemente necesite saber qué está escrito y qué no, para volver a enviarlo por completo. Probablemente ... O tal vez incluir una sola versión de Prefs en el archivo será suficiente. No sé, estoy trabajando en esto para evitar algunos problemas en el futuro con viejos archivos de Preferencia. ¿Conoces una buena fuente de lectura sobre esto? – Oliver

+0

esos valores predeterminados no se escriben en NSUserDefaults (es por eso que debe registrarlos en cada lanzamiento), cuando desea nuevos valores predeterminados en una versión posterior, solo registre nuevos valores predeterminados. Si el usuario nunca tocó una configuración, se utilizan los nuevos valores predeterminados, si ha cambiado la configuración, lo más probable es que quiera usar su propia configuración de todos modos. –

8

Puede probar utilizando objectForKey: y si es nulo, entonces no está configurado. Todo boolForKey lleva el NSNumber devuelto si lo hay y devuelve un valor de BOOL.

+3

Nota para los usuarios de MonoTouch: el método 'ObjectForKey (clave)' es inaccesible porque está marcado como interno. En su lugar, use el indexador: 'NSUserDefaults.StandardUserDefaults [key]'. –

29

Compruebe si el objeto existe antes de la conversión a BOOL.

if ([defaults objectForKey:@"theBoolKey"] != nil) { 
    boolFromPrefs = [defaults boolForKey:@"theBoolKey"]; 
} else { 
    boolFromPrefs = DEFAULT_BOOL_VALUE; 
} 
+2

No funcionará si bool es falso. – phatmann

+0

@phatmann ¿por qué es eso? afaik, ObjectForKey devolverá nil si no está configurado, 0 si es falso y 1 si es verdadero. – Pega88

+0

@ Pega88 Definitivamente estaba teniendo problemas con este enfoque en una versión anterior de iOS, y otras personas han notado el mismo problema. De hecho, esta es la razón por la que busqué stackoverflow.No sé si este comportamiento ha cambiado en los sistemas operativos más recientes y cuáles son las condiciones exactas para que suceda. – phatmann

2

Recomendaría establecer valores predeterminados para cualquier tecla que su aplicación pueda usar. Puedes hacer esto en la aplicación: didFinishLaunchingWithOptions: method. De esa forma sabrá que cada valor ha sido establecido.

Sugerencia, establezca una clave llamada "defaultsSet" en SÍ para que solo haga esto una vez. Además, recuerde llamar a [[NSUserDefaults standardUserDefaults] synchronize] para guardar los valores.

+0

¿Qué quiere decir con "establecer una clave llamada" defaultsSet "en SÍ para que solo lo haga una vez"? – Oliver

+0

Lo sugerí como una forma de asegurarse de que los valores predeterminados solo se establezcan una vez y no sobrescriban los cambios del usuario. Podría llamarlo cualquier cosa, simplemente es otra clave configurada con un valor conocido. – picciano

+0

Lo siento, puedo estar cansado, pero todavía no entiendo exactamente lo que quieres decir. ¿Podría darme un ejemplo, por favor? – Oliver

24

lo hice de esta manera:

NSUserDefaults *prefs = NSUserDefaults.standardUserDefaults; 
if ([[prefs dictionaryRepresentation].allKeys containsObject:@"yourKey"]) { 
    float yourValue = [prefs floatForKey:@"yourKey"]; 
} 
+0

Esta es la mejor solución debido al hecho de que el valor podría EQUAL 0, por lo que evaluar el valor devuelto podría ser incorrecto. – avenged

+0

Me preocupa el rendimiento. ¿Tomará tiempo convertir los valores predeterminados del usuario en un diccionario cada vez? –

0

Ejemplo Swift basado en la respuesta de MarkPowell

if (NSUserDefaults.standardUserDefaults().objectForKey("SomeBoolSetting") == nil) { 
    NSUserDefaults.standardUserDefaults().setBool(true, forKey: "SomeBoolSetting") 
    println("Bool WAS nil") 
} else { 
    var boolValue:Bool? = NSUserDefaults.standardUserDefaults().boolForKey("SomeBoolSetting") 
    println("Bool WAS NOT nil \(boolValue)") 
} 
0

versión rápida de @Tim Autin 's respuesta:

if contains(NSUserDefaults.standardUserDefaults().dictionaryRepresentation().keys.array, "chuiser_cook_orders_dirty") { 
    println("exist") 
} 
+0

La sintaxis de Swift 3 es aún más limpia, reduciendo el condicional a: 'UserDefaults.standard.dictionaryRepresentation(). Keys.index (de:" chuiser_cook_orders_dirty ")! = Nil' –

0

No te compliques :

if([NSUserDefaults.standardUserDefaults objectForKey:@"yourBoolKey"]) 
{ 
    // Object Already Stored in User defaults 
} 
else 
{ 
    //Object not stored 
} 
Cuestiones relacionadas