2011-04-16 19 views
51

Tengo un código que detecta si NSString es NULL, nil, etc. Sin embargo, falla. Aquí está mi código:Cómo detectar si NSString es nulo?

NSArray *resultstwo = [database executeQuery:@"SELECT * FROM processes WHERE ready='yes' LIMIT 0,1"]; 
for (NSDictionary *rowtwo in resultstwo) { 

NSString *getCaption = [rowtwo valueForKey:@"caption"]; 

if (getCaption == NULL) { 
theCaption = @"Photo uploaded..."; 
} else if (getCaption == nil) { 
theCaption = @"Photo uploaded..."; 
} else if ([getCaption isEqualToString:@""]) { 
theCaption = @"Photo uploaded..."; 
} else if ([getCaption isEqualToString:@" "]) { 
theCaption = @"Photo uploaded..."; 
} 

} 

Y aquí está el error:

Terminating app due to uncaught exception ' NSInvalidArgumentException ', reason: ' -[NSNull isEqualToString:] : unrecognized selector sent to instance 0x3eba63d4 '

¿Estoy haciendo algo mal? ¿Debo hacerlo de otra manera?

+1

¿Cuál es el tipo de datos de 'rowtwo'? ¿Por qué lo estás enviando '-valueForKey:'? –

+3

Dejaré este comentario para referencia adicional: '-valueForKey:' es un método KVC. En KVC, '[NSNull null]' representa la ausencia de un valor para una clave dada. Si está utilizando un 'NSDictionary' en un contexto que no necesita KVC, use' -objectForKey: 'en su lugar - devolverá' nil' en lugar de '[NSNull null]' cuando una clave dada no esté presente en el diccionario. –

+1

Consulte esta pregunta sobre desbordamiento de pila para ver una discusión sobre la diferencia entre '-valueForKey:' y '-objectForKey:': http://stackoverflow.com/questions/1062183/objective-c-whats-the-difference-between-objectforkey -and-valueforkey –

Respuesta

163

El valor NULL para Objective-C objetos (tipo id) es nil.

Mientras NULL se utiliza para C punteros (tipo void *).

(Al final ambos terminan sosteniendo el mismo valor (0x0) Se diferencian en el tipo sin embargo..)

En Objective-C:

  • nil(todo en minúsculas) es un puntero nulo a un objeto Objective-C.
  • Nil(mayúscula) es un puntero nulo a una clase Objective-C.
  • NULL(todos los casquillos) es un puntero nulo a cualquier otra cosa (C punteros, que es).
  • [NSNull null] es un singleton para situaciones en las uso de nil no es posible (añadiendo/recepción nil a/desde NSArray s por ejemplo)

En Objective-C++:

  • Todo lo anterior, plus:
  • null(minúsculas) o nullptr (C++ 11 o posterior) es un puntero nulo a objetos C++.

Así, para comprobar contra nil usted debe o comparar con nil (o NULL respectivamente) explícitamente:

if (getCaption == nil) ... 

o dejar ObjC/C lo hace implícitamente para usted:

if (!getCaption) ... 

Esto funciona como cada expresión en C (y con Objective-C ser un superconjunto de los mismos) tiene un valor booleano implícito:

expression != 0x0 => true 
expression == 0x0 => false 

Ahora, cuando la comprobación de NSNull esto obviamente no funcionaría como [NSNull null] devuelve un puntero a una instancia singleton de NSNull, y no nil, y por lo tanto no es igual a 0x0.

Así, para comprobar contra NSNull uno puede usar:

if ((NSNull *)getCaption == [NSNull null]) ... 

o (preferido, ver comentarios):

if ([getCaption isKindOfClass:[NSNull class]]) ... 

Tenga en cuenta que esta última (que utiliza una llamada del mensaje) devolverá false si getCaption es nil, que, aunque formalmente correcto, puede no ser lo que espera/desea.

Por tanto, si uno (por cualquier razón) necesaria para cheque en contra de ambosnil/NULLyNSNull, habría que combinar esos dos cheques:

if (!getCaption || [getCaption isKindOfClass:[NSNull class]]) ... 

Para obtener ayuda en la formación verificaciones positivas equivalentes ver De Morgan's laws y boolean negation.

Editar:NSHipster.com publicado recientemente un artículo sobre las diferencias sutiles entre nulo, nulo, etc.

+2

Es cierto, aunque el error real es que '[rowtwo valueForKey: @" caption "]' devuelve una instancia 'NSNull' en lugar de una instancia' NSString'. –

+0

@Bavarious: Vea la última línea en la respuesta. – Regexident

+0

¡Gracias, funciona! – iosfreak

23

Debe utilizar

if ([myNSString isEqual:[NSNull null]])

Esto comprobará si el objeto es igual a myNSString Objeto NSNull.

+4

Como NSNull es un singleton, puedes comparar los punteros directamente: 'if (getCaption == [NSNull null]) ...' – Caleb

+1

¡Pero comparar el singleton es una mala idea! No lo hagas = X [NSNull null] puede ser un singleton pero NSNull es una clase como cualquier otra. – Dustin

2
if([getCaption class] == [NSNull class]) 
    ... 

También se puede hacer

if([getCaption isKindOfClass:[NSNull class]]) 
    ... 

si quieres ser a prueba de futuro contra nuevas subclases de NSNull.

+1

De todas las respuestas en esta página, solo su respuesta principal funciona para mí en Xcode 6.1, usando una propiedad NSString llamada 'body' que es nula.Salida del depurador: '_body \t NSString * class name = NSNull \t 0x0000000107279ce0' y' Imprimir descripción del anuncio -> _ body: ' –

6

Preferido forma de comprobar la NSNULL es

if(!getCaption || [getCaption isKindOfClass:[NSNull class]]) 
2

Del cheque con este código:

NSString *object; 

if(object == nil) 

Esto debería funcionar.