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
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])
OR
if(![myArray isKindOfClass:[NSNull class]])
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"])) ...
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.
J'ai trouvé le code pour travailler avec NSNull
a les problèmes suivants:
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:
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.
Dans Swift (ou comme pont entre Objective-C), il est possible d'avoir NSNull
et nil
dans un tableau d'options NSArray
s 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
}
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).
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.
}
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:
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"