2010-11-20 17 views
5

Primero confieso mi ignorancia, he aprendido todo lo que sé sobre Objective-C en los pocos meses que he estado trabajando en mi proyecto. También me parece totalmente frustrante cómo Objective-C parece complicar lo que serían simples asuntos en cualquier otro idioma con el que haya trabajado. Esta pregunta es un caso puntual ...Cómo verificar el valor nulo en NSNumber

En la primera ejecución, mi aplicación descarga un montón de JSON que utiliza para llenar una tienda CoreData. Utilizo una biblioteca Obj-C/JSON (CJSONDeserializer) para convertir el JSON en NSArrays. En la descarga JSON para una entidad CoreData, hay un campo que contiene un número ("show_id":2) que identifica el campo relacionado en otra entidad, si hay uno o nulo ("show_id":null) en caso contrario. En la tramitación de este campo le asigno a un NSNumber usando ...

NSNumber *shoIndex = [[item objectForKey:typeKey] objectForKey:@"show_id"]; 

que luego tratar de comprobar que tengo un número válido antes de intentar a buscar & enlace al registro relacionado con el fin de no hacer el proceso donde hay desperdicio no es un registro relacionado.

Interrogar shoIndex con ...

NSLog(@"shoIndex: %i, %@, %@", shoIndex, shoIndex, [shoIndex description]); 

Da ...

shoIndex: 19590600, <null>, <null> 

donde el valor JSON fue null & ...

shoIndex: 228300880, 51, 51 

lo contrario.

Hasta ahora la única prueba con éxito que he hecho es con ...

if (![[shoIndex description] isEqualToString:@"<null>"]) { 

¿Puede alguien sugerir una mejor manera?

actualización ...

Visto de otro modo shoIndex se asigna como NSNumber que a veces contiene un valor NSString@"<null>". ¿Obj-C tiene algo así como un operador isa que podría utilizar para verificar el tipo de contenido de shoIndex?

TIA, Pedro.

+0

Qué le hace pensar que el objeto es una instancia de 'NSNumber'? – jlehr

Respuesta

10

Usa [shoObject class] para obtener la clase de un objeto; Por lo tanto, para probar shoObject 's de clase, se usaría

[shoObject isKindOfClass:[NSString class]]; 

Una vez que haya resuelto lo marcadores definen una cadena vacía o NSNumber, puede crear una macro. Lo hago manteniendo una macro IsEmpty en un archivo llamado CommonMacros.h. Aquí está el código:

//Thanks Wil 
//http://wilshipley.com/blog/2005/10/pimp-my-code-interlude-free-code.html 

static inline BOOL IsEmpty(id thing) { 
    return thing == nil 
    || ([thing isEqual:[NSNull null]]) //JS addition for coredata 
    || ([thing respondsToSelector:@selector(length)] 
     && [(NSData *)thing length] == 0) 
    || ([thing respondsToSelector:@selector(count)] 
     && [(NSArray *)thing count] == 0); 
} 

Luego, después de importar CommonMacros.h, puede llamar a la función como esta:

if (IsEmpty(shotIndex)) { 
    //do stuff 
} 

Esto debe hacerse cargo de este problema, y ​​también trabajará en cadenas, matrices, etc., como se puede ver en el código. Gracias a Wil Shipley!

+0

Gracias Wil, eso funciona como un regalo. Al mirar la URL que diste allí, creo que ya me has ayudado de otras maneras :) – Pedro

+0

Hablé demasiado pronto. Quiero hacer cosas si shoIndex no está vacío, ¡así que lo intenté! IsEmpty (shoIndex) y mi NSNumber vuela directo. – Pedro

+0

Hmm, extraño, eso es muy malo. Sugeriré que se agregue esta prueba de isEqualToString: @ "" al código de IsEmpty, pero por supuesto eludir esa ruta es la razón por la que hizo esta pregunta en primer lugar. –

-1

En Objective-c, es nil no null. Entonces:

if (shotIndex != nil) { 
    // its not nil 
} 
+2

Esto es exactamente lo que probé por primera vez y no funcionó. Donde vea en mi pregunta, eso es lo que NSLog da para NSNumber donde el elemento JSON era nulo. – Pedro

+0

Esto es JSON. Si el shotIndex no estaba presente en los datos JSON, entonces sería nulo. Sin embargo, como dijo Pedro, el shotIndex estaba presente con un valor de nulo, y los analizadores de JSON le darán un valor de [NSNull null], no nulo. El envío de la mayoría de los mensajes a [NSNull null] se bloqueará, por lo que esta es una diferencia importante. – gnasher729

0

En algunos casos, como las teclas faltantes en NSUserDefaults, recuperas el literal @ "" como una cadena vacía.

Aquí está mi comprobación segura de un NSNumber.

Nota del cheque para que sea una NSNumber se produce en primer lugar porque no entiende NSNumber isEqualToString

 id savedPin = [[NSUserDefaults standardUserDefaults] valueForKey:@"blah"]; // don't assume is created so don't type as NSNumber* 
     if (![savedPin isKindOfClass:[NSNumber class]] && [savedPin isEqualToString:@""]) {