2010-01-13 10 views
18

que hemos probado algo a lo largo de las líneas de:¿Objective-C usa la evaluación de cortocircuito?

if(myString != nil && myString.length) { ... } 

Y tiene:

- [longitud NSNull]: Selector no reconocido enviado a la instancia

¿Tiene Objective-C provoque un cortocircuito después de la primera la condición falla?

+1

¿'NSNull' es igual a 'nil'? –

+4

No. NSNull y nil no son lo mismo. De ningún modo. – bbum

Respuesta

30

Objective-C es compatible con la evaluación de corto circuito, al igual que C.

Parece que en su ejemplo es myStringNSNull y no nil, por lo tanto, myString != nil es cierto.

NSNull es un singleton y se usa para representar nil donde solo se permiten objetos, por ejemplo en un NSArray.

Por cierto, las personas escriben if (!myString && myString.length == 0). Comparar con nil es bastante feo. Además, compararía la longitud con 0. Eso parece ser más claro.

+0

Gracias por la sugerencia. Todavía estoy tratando de alinearme con todas las convenciones de sintaxis y nomenclatura. – kwcto

+7

No diría que la gente "normalmente" no se compara con nada. Lo he visto hecho en ambos sentidos con la misma frecuencia. El argumento es que puedes leerlo como 'si myString no es nulo' en lugar de 'if not myString'. – bobDevil

+0

En realidad, es incorrecto comparar con nil via (nil == variable) es la forma correcta de asegurar que un mensaje no se envíe a un objeto nulo. –

10

Objective-C es un superconjunto estricto de C.

Debido C apoya evaluación de cortocircuito, Objective-C también lo hace.

+1

NString * str = expressionThatReturnsStrOrNil() || @ ""; No funciona. Esta es una evaluación de cortocircuito que no funciona. –

+1

@PedroMorteRolo: Por supuesto que funciona. ¿Qué resultado esperas? (Tenga en cuenta que el resultado del operador '||' es '1' o' 0', nunca más). –

+1

Tienes razón. Caí en la ilusión de que C tenía la misma semántica que Ruby. –

3

¿Qué es NSNull definido como? Si se trata de un objeto que se supone que no representa nada, entonces no sería nulo. en otras palabras, NSNull y nil no son lo mismo.

0

Si tiene un NSNull en alguna parte, probablemente esté usando un analizador JSON o CoreData. Cuando un número en CoreData no está configurado, CoreData le devolverá NSNull; posiblemente lo mismo ocurra con los valores de NSString en CoreData.

De forma similar, puede tener elementos vacíos en JSON devueltos por un servidor y algunos analizadores le darán eso como un objeto NSNull. Por lo tanto, en ambos casos, debe tener cuidado cuando use valores, ya que lo que usted pensó que era un objeto NSSumerg o NSNumber es realmente NSNull.

Una solución es definir una categoría en NSNull que simplemente ignora todos los mensajes no comprendidos que se envían al objeto, según el código siguiente. Entonces el código que tiene funcionaría porque NSNull.length devolvería 0. Puede incluir algo como esto en su archivo de proyecto .pch, que se incluye en cada archivo de su proyecto.

// NSNull+IgnoreMessages.h 
@interface NSNull(IgnoreMessages) 
- (void)forwardInvocation:(NSInvocation *)anInvocation; 
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector; 
@end 

//NSNull+IgnoreMessages.m 
#import "NSNull+IgnoreMessages.h" 
@implementation NSNull(IgnoreMessages) 
- (void)forwardInvocation:(NSInvocation *)anInvocation 
{ 
    if ([self respondsToSelector:[anInvocation selector]]) 
     [anInvocation invokeWithTarget:self]; 
} 

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 
{ 
    NSMethodSignature *sig=[[NSNull class] instanceMethodSignatureForSelector:aSelector]; 
     // Just return some meaningless signature 
    if(sig==nil) 
     sig=[NSMethodSignature signatureWithObjCTypes:"@^v^c"]; 

    return sig; 
} 
@end 
+0

Eso solo está esperando para fallar. Es importante saber cuándo se trata de 'NSNull' en lugar de' nil', su código lo hace menos probable. En el ejemplo de la pregunta, hay un mensaje de error que contiene 'NSNull', no lo verías con tu código y' if (myString) 'todavía se evaluaría como verdadero. –

+0

Así que dígame cómo puede fallar si puede enviar cualquier mensaje a él, al igual que nada ... y seguirá llamando a cualquier mensaje realmente entendido por NSNull (incluidos todos los métodos de NSObject). Ahora puede causar errores, en el sentido de que si marca expresamente la equivalencia a cero eso no será cierto. Pero en la mayoría de las codificaciones, exactamente porque nil se puede enviar cualquier mensaje que acabo de probar en contra de algo como (myString.length> 0) que funciona bien aquí. De hecho, este código PREVENIRá posibles bloqueos en su código cuando un NSNull se desliza donde usted no lo esperaba, por lo que en la balanza se trata de una ganancia de estabilidad. –

+0

Además, ¿dónde dice que es un mensaje de error? Eso ni siquiera tiene sentido, ¿por qué algo que quiera devolver un mensaje de error alguna vez enviará NSNull en lugar de un NSString? En la práctica, solo he visto NSNull saliendo de CoreData y algunos JSON Parsers, de forma que esta prueba no hace más que evitar errores de tiempo de ejecución no obvios. Aún puede verificar NSNull donde sea importante. –

Cuestiones relacionadas