web-dev-qa-db-fra.com

Comment puis-je vérifier si un objet dans un NSArray est NSNull?

Je reçois un tableau avec une valeur nulle. Veuillez vérifier la structure de mon tableau ci-dessous:

 (
    "< null>"
 )

Lorsque j'essaie d'accéder à l'index 0, il se bloque à cause de

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

Actuellement, il se bloque à cause de ce tableau avec un journal de crash:

 *** 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
59
Navi
id object = myArray[0];// similar to [myArray objectAtIndex:0]

if(![object isEqual:[NSNull null]])
{
    //do something if object is not equals to [NSNull null]
}
117
Charith Nidarsha
if (myArray != (id)[NSNull null])

OR

if(![myArray isKindOfClass:[NSNull class]]) 
29
Toni Albuquerque

En me basant sur la réponse de Toni, je fis une macro.

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

Puis l'utiliser

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

Awww, les gars. C'est facile.

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

Je suis sûr qu'il existe de meilleures réponses, mais celle-ci fonctionne.

7
Alex Zavatone

J'ai trouvé le code pour travailler avec NSNull a les problèmes suivants: 

  • Ça a l'air bruyant et moche. 
  • Long. 
  • Erreur sujette. 

J'ai donc créé la catégorie suivante: 

@interface NSObject (NSNullUnwrapping)

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

@end

Avec la mise en œuvre:

@implementation NSObject (NSNullUnwrapping)

- (id)zz_valueOrNil
{
    return self;
}

@end

@implementation NSNull (NSNullUnwrapping)

- (id)zz_valueOrNil
{
    return nil;
}

@end

Il fonctionne selon les règles suivantes:

  • Si une catégorie est déclarée deux fois pour le même Class (c'est-à-dire une instance singleton du type Class), le comportement n'est pas défini. Cependant, une méthode déclarée dans une sous-classe est autorisée à remplacer une méthode category dans sa super-classe. 

Cela permet d'avoir un code plus concis:

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

. . au lieu d'avoir des lignes supplémentaires pour vérifier NSNull. Le préfixe zz_ a l’air un peu moche mais la sécurité permet d’éviter les collisions entre espaces de noms. 

6
Jasper Blues

Dans Swift (ou comme pont entre Objective-C), il est possible d'avoir NSNull et nil dans un tableau d'options NSArrays ne peut contenir que des objets et n'aura jamais nil, mais peut avoir NSNull. Un tableau Swift de types Any? peut cependant contenir nil.

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

Pour vérifier par rapport à NSNull, utilisez is pour vérifier le type d'un objet. Ce processus est le même pour les tableaux Swift et les objets NSArray:

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

Vous pouvez également utiliser un if let ou guard pour vérifier si votre objet peut être converti en NSNull:

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

ou

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

Beaucoup de bonnes et intéressantes réponses ont déjà été données et toutes fonctionnent. 

Juste pour terminer (et le plaisir): 

[NSNull null] permet de renvoyer un singleton. Donc 

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

fonctionne bien aussi. 

Cependant, comme il s'agit d'une exception, je ne pense pas que l'utilisation de == pour comparer des objets soit une bonne idée en général. (Si je revoyais votre code, je ferais certainement des commentaires à ce sujet).

2
Hermann Klecker

Considérez cette approche:

Option 1:

NSString *str = array[0];

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

Option 2:

NSString *str = array[0];
str = str == (id)[NSNull null]? nil : str;

if (str.length > 0) {
   // you have a valid string.
} 
2
Wayne

Vous pouvez utiliser le chèque suivant:

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

La raison de ceci se trouve sur la documentation officielle d'Apple:

Utiliser NSNull

La classe NSNull définit un objet singleton que vous utilisez pour représenter les valeurs null dans les situations où nil est interdit en tant que valeur (généralement dans un objet de collection tel qu'un tableau ou un dictionnaire).

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

Il est important de comprendre que l'instance de NSNull est sémantiquement différente de NO ou de false, ces deux valeurs représentant une valeur logique. l'instance NSNull représente l'absence d'une valeur. L'instance NSNull est sémantiquement équivalente à nil, mais il est également important de comprendre qu'elle n'est pas égale à nil. Pour tester une valeur d'objet nulle, vous devez donc effectuer une comparaison d'objet directe.

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"

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

0
Marky