ios objective-c nsarray nsnull

ios - ¿Cómo puedo verificar si un objeto en un NSArray es NSNull?



objective-c (9)

Awww, chicos. Esta es una fácil.

// if no null values have been returned. if ([myValue class] == [NSNull class]) { myValue = nil; }

Estoy seguro de que hay mejores respuestas, pero esta funciona.

Estoy obteniendo una matriz con valor nulo. Por favor, compruebe la estructura de mi matriz a continuación:

( "< null>" )

Cuando intento acceder al índice 0, se bloquea debido a

-[NSNull isEqualToString:]: unrecognized selector sent to instance 0x389cea70

Actualmente se bloquea debido a esa matriz con un registro de bloqueo:

*** Terminating app due to uncaught exception ''NSInvalidArgumentException'', reason: ''-[NSNull isEqualToString:]: unrecognized selector sent to instance 0x389cea70'' *** First throw call stack: (0x2d9fdf53 0x3820a6af 0x2da018e7 0x2da001d3 0x2d94f598 0x1dee57 0x1dfd31 0x302f598d 0x301a03e3 0x3052aeed 0x3016728b 0x301659d3 0x3019ec41 0x3019e5e7 0x30173a25 0x30172221 0x2d9c918b 0x2d9c865b 0x2d9c6e4f 0x2d931ce7 0x2d931acb 0x3262c283 0x301d3a41 0xabb71 0xabaf8) libc++abi.dylib: terminating with uncaught exception of type NSException


Considera este enfoque:

Opción 1:

NSString *str = array[0]; if ( str != (id)[NSNull null] && str.length > 0 { // you have a valid string. }

Opcion 2:

NSString *str = array[0]; str = str == (id)[NSNull null]? nil : str; if (str.length > 0) { // you have a valid string. }


En Swift (o puente desde Objective-C), es posible tener NSNull y nil en una matriz de opciones. NSArray s solo puede contener objetos y nunca tendrá nil , pero puede tener NSNull . Una matriz Swift de Any? los tipos pueden contener nil , sin embargo.

let myArray: [Any?] = [nil, NSNull()] // [nil, {{NSObject}}], or [nil, <null>]

Para verificar contra NSNull , el uso is para verificar el tipo de un objeto. Este proceso es el mismo para las matrices Swift y los objetos NSArray :

for obj in myArray { if obj is NSNull { // object is of type NSNull } else { // object is not of type NSNull } }

También puede usar un if let o guard para verificar si su objeto puede ser NSNull a NSNull :

guard let _ = obj as? NSNull else { // obj is not NSNull continue; }

o

if let _ = obj as? NSNull { // obj is NSNull }


Encontré que el código para trabajar con NSNull tiene los siguientes problemas:

  • Se ve ruidoso y feo.
  • Pérdida de tiempo.
  • Propenso a errores.

Así que creé la siguiente categoría:

@interface NSObject (NSNullUnwrapping) /** * Unwraps NSNull to nil, if the object is NSNull, otherwise returns the object. */ - (id)zz_valueOrNil; @end

Con la implementación:

@implementation NSObject (NSNullUnwrapping) - (id)zz_valueOrNil { return self; } @end @implementation NSNull (NSNullUnwrapping) - (id)zz_valueOrNil { return nil; } @end

Funciona según las siguientes reglas:

  • Si una categoría se declara dos veces para la misma Class (es decir, instancia única del tipo Class ), el comportamiento no está definido. Sin embargo, un método declarado en una subclase puede anular un método de categoría en su superclase.

Esto permite un código más directo:

[site setValue:[resultSet[@"main_contact"] zz_valueOrNil] forKey:@"mainContact"];

. . en lugar de tener líneas adicionales para comprobar NSNull . El prefijo zz_ ve un poco feo, pero hay seguridad para evitar colisiones de espacio de nombres.


Partiendo de la respuesta de Toni hice una macro.

#define isNSNull(value) [value isKindOfClass:[NSNull class]]

Entonces para usarlo

if (isNSNull(dict[@"key"])) ...


Puede usar la siguiente verificación:

if (myArray[0] != [NSNull null]) { // Do your thing here }

El motivo de esto se puede encontrar en los documentos oficiales de Apple:

Usando NSNull

La clase NSNull define un objeto singleton que se usa para representar valores nulos en situaciones donde nil está prohibido como un valor (generalmente en un objeto de colección como una matriz o un diccionario).

NSNull *nullValue = [NSNull null]; NSArray *arrayWithNull = @[nullValue]; NSLog(@"arrayWithNull: %@", arrayWithNull); // Output: "arrayWithNull: (<null>)"

Es importante apreciar que la instancia de NSNull es semánticamente diferente de NO o falsa, ambas representan un valor lógico; la instancia NSNull representa la ausencia de un valor. La instancia de NSNull es semánticamente equivalente a cero, sin embargo, también es importante apreciar que no es igual a cero. Para probar un valor de objeto nulo, debe hacer una comparación directa de objetos.

id aValue = [arrayWithNull objectAtIndex:0]; if (aValue == nil) { NSLog(@"equals nil"); } else if (aValue == [NSNull null]) { NSLog(@"equals NSNull instance"); if ([aValue isEqual:nil]) { NSLog(@"isEqual:nil"); } } // Output: "equals NSNull instance"

Tomado de https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/NumbersandValues/Articles/Null.html


Ya se han dado muchas buenas e interesantes respuestas y (nealry) todas funcionan.

Solo para completar (y lo divertido):

[NSNull null] está documentado para devolver un singleton. Por lo tanto

if (ob == [NSNull null]) {...}

funciona bien también

Sin embargo, como esta es una excepción, no creo que usar == para comparar objetos sea una buena idea en general. (Si revisara tu código, ciertamente comentaría sobre esto).


id object = myArray[0];// similar to [myArray objectAtIndex:0] if(![object isEqual:[NSNull null]]) { //do something if object is not equals to [NSNull null] }


if (myArray != (id)[NSNull null])

O

if(![myArray isKindOfClass:[NSNull class]])