J'ai cherché comment vérifier si la clé NSDictionary existe ou non et j'ai trouvé la solution. Mais cela me lance quand même une erreur en ajoutant une valeur nulle à la clé. Je ne sais pas si mon code est correct ou non. Si quelqu'un a une idée à ce sujet, il peut m'aider.
NSDictionary *result;
id myImageURL = [result objectForKey:@"url"];
if ((NSNull *)myImageURL == [NSNull null])
myImageURL = @"";
id myImage = [result objectForKey:@"image"];
if ((NSNull *)myImage == [NSNull null])
myImage = @"";
Vérifiez si null n’ajoute rien et si non, ajoutez la valeur. Mais cela me donne toujours une erreur, je ne sais pas pourquoi.
/****OUTPUT*****/
2011-08-11 14:56:06.668 Tab_Table_Win[6510:207] RESULTS : {
image = "<UIImage: 0xbc332c0>";
url = "http://a3.twimg.com/profile_images/999228511/normal.jpg";
}
2011-08-11 14:56:06.669 Tab_Table_Win[6510:207] url : http://a3.twimg.com/profile_images/999228511/normal.jpg
2011-08-11 14:56:06.670 Tab_Table_Win[6510:207] IMage : <UIImage: 0xbc332c0>
/*****Breaks Here ***/
2011-08-11 14:56:06.876 Tab_Table_Win[6510:207] RESULTS : {
}
2011-08-11 14:56:06.878 Tab_Table_Win[6510:207] url : (null)
2011-08-11 14:56:06.879 Tab_Table_Win[6510:207] IMage : (null)
2011-08-11 14:56:06.881 Tab_Table_Win[6510:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil key'
La réponse correcte est:
NSDictionary *result;
NSURL *myImageURL = [result objectForKey:@"url"];
UIImage *myImage = [result objectForKey:@"image"];
/**** Correct way ****/
if (myImageURL != nil && myImage != nil) {
[images setObject:myImage forKey:myImageURL];
}
Merci pour toutes les explications.
Tommy a parfaitement expliqué cela.
Ce que je recommande est de créer une extension de la classe NSDictionary comme suit:
#import <Foundation/Foundation.h>
@interface NSDictionary (Safety)
- (id)safeObjectForKey:(id)aKey;
@end
Et le fichier d'implémentation:
#import "NSDictionary+Safety.h"
@implementation NSDictionary (Safety)
- (id)safeObjectForKey:(id)aKey {
NSObject *object = self[aKey];
if (object == [NSNull null]) {
return nil;
}
return object;
}
@end
Et au lieu d'utiliser [dictionary objectForKey:@"keyName"];
dans votre code, utilisez
[dictionary safeObjectForKey:@"keyName"];
Ainsi, comme l'explique Tommy, vous enverriez un appel de méthode à un élément null qui ne planterait pas l'application, mais votre objet obtiendrait une valeur nulle.
J'espère que cela t'aides.
la réponse ci-dessous a fonctionné pour moi:
https://stackoverflow.com/a/2784675/936957
if ([dictionary objectForKey:key]) {
// previously stored data for "key"
}
Notez également que vous pouvez obtenir un tableau des clés dans un dictionnaire en utilisant
[dictionary allKeys]
Chaque fois que j'essaie de vérifier si un objet renvoyé par un dictionnaire est null, je le fais:
id obj = [myDictionary objectForKey:entityKeyName];
if (obj == [NSNull null]) {
// do something
}
Ensuite, dans votre code, ce serait:
NSDictionary *result;
NSString *myImageURL = [result objectForKey:@"url"];
if (myImageURL == [NSNull null])
myImageURL = @"";
C'est ce que je ferais dans votre code.
De plus, le résultat de NSDictionary est-il défini? Dans votre code, rien ne le configure. Il est juste défini comme variable que vous prévoyez d'utiliser des résultats appelés
Si un objet n'existe pas pour une clé, NSDictionary retournera nil
. Un NSNull
est un objet réel, et donc une chose distincte. C'est comme la distinction entre pouvoir enregistrer qu'il y avait une valeur et la valeur comme nulle, et ne pas enregistrer s'il y avait une valeur. Cela dépend aussi un peu de votre pensée en termes C de l'indirection d'un pointeur vers un objet plutôt que simplement d'un objet, de sorte que ce n'est pas complètement sémantique de ce point de vue.
En Objective-C, vous pouvez envoyer n’importe quel message à nil
et le résultat obtenu est nil
(ou 0). Donc, si votre code est conçu pour garantir que vous avez une référence d'objet sécurisé, comme vous le feriez peut-être en C++, ce que vous faites est inutile. Des énoncés composés comme:
object = [[Type alloc] init];
Sont toujours explicitement en sécurité, même si alloc échoue et renvoie nil
. Tout ce qui va se passer, c'est que l'appel à init
ne fera rien du tout et que l'objet se retrouvera avec la valeur nil
car le résultat de l'envoi de init
à nil
est également nil
.
Cela étant dit, les réponses fournies par Bill et Emmanuel devraient être correctes. Comparez votre résultat soit directement à nil
, soit implicitement à zéro. Si vous rencontrez un plantage plus tard, je suppose que c'est parce que vous vous attendez à ce que myImageUrl
et myImage
soient des types autres que NSString
(je remarque que vous avez utilisé le id
sans type dans votre code d'origine) et vous leur envoyez un message. ne répond pas à.
cette autre option:
if (![result objectForKey:@"image"])
{
NSLog(@"doesn't exist");
}
if ([result objectForKey:@"image"])
{
NSLog(@"exist");
}
NSDictionary *result;
NSString *myImageURL = [result objectForKey:@"url"];
if (myImageURL == NULL)
myImageURL = @"";
NSString *myImage = [result objectForKey:@"image"];
if (myImageURL == NULL)
myImage = @"";
Voyez si cela fonctionne, plutôt que de trop penser à la classe NULL.
ça ne marchait pas pour moi, je l'ai compris comme ça
id myImageURL = [result objectForKey:@"url"];
if ([myImageURL isKindOfClass:[NSNull class]])
myImageURL = @"";
Très bien voici la réponse que presque @Iomec avait presque
UIImage *myImage = ([result objectForKey:@"image"] != [NSNull null] ? [result objectForKey:@"image"] : nil);
C’est la bonne réponse car elle est nulle et quand vous dites myImage = [receiveObject ...]; alors si myImage = nil, vous convertissez une valeur nulle (nil) dans une classe qui est une exception, sinon un bogue en cours d'exécution.
Vous devez: 1) tester la valeur null NSNull 2) sinon, attribuer
Si votre code n'a pas encore été corrigé, il le sera en production lorsque vous exécuterez 8 applications en tâche de fond un jour.
Lorsque vous appelez le dictionnaire objectForKey
in nullable, l'application se bloque, j'ai donc corrigé le problème de cette façon afin d'éviter tout blocage.
- (instancetype)initWithDictionary:(NSDictionary*)dictionary {
id object = dictionary;
if (dictionary && (object != [NSNull null])) {
self.name = [dictionary objectForKey:@"name"];
self.age = [dictionary objectForKey:@"age"];
}
return self;
}
J'ai le même problème avec JSONKit. La mise en place il y a
- (id)objectForKey:(id)aKey
{
[...]
return((entryForKey != NULL) ? entryForKey->object : NULL);
}
Donc, ceci retournera certainement NULL si l'objet n'est pas là. Je vérifie comme suit
NSArray* array = [myDictionary objectForKey:@"a"];
if((NSNull*)arrays!=[NSNull null])
{
[...]
}
1. Results Dictionary after JSON parsing:
//if hits success
{"result":{"action":"authentication","statusCode":"200","statusMsg":"No
error, operation
successful.","count":1,"data":{"apiToken":"509e6d21-4f69-4ded-9f3d-4537e59e6a3a","userId":8,"role":"Bidder","firstName":"bidder","lastName":"bidder","emailAddress":"[email protected]","countiesCovered":"21,16,11,1,2,14,32,3,4,25,13,15,5,41,43,6,12,7,24,39,17,36,42,44,29,40,8,18,19,27,9,28,23,10,33,26,35,20,30,22,34,31"}}}
//Data is Dictionary inside Result
-----------------------------------------------------------------------
I had an error showing : NULL DATACould not cast value of type 'NSNull' (0xda7058) to 'NSDictionary' (0xda6d74) and the result was
the following.
({"result":{"action":"authentication","statusCode":"204","statusMsg":"Invalid
Username or Password","count":null,"data":null}})
I fixed the Null check of dictionary.
if (result.objectForKey("data") is NSNull)
{
print ("NULL DATA")
}
else
{
let data = result["data"]as! NSDictionary
print (data)
}
Peut-être voudriez-vous ajouter un peu plus de sécurité en vérifiant pour vous assurer qu'il ne s'agit PAS d'une chaîne de caractères au lieu de simplement vérifier si IS est nul. (Pour vous assurer que ce n'est pas un nombre ou quoi que ce soit d'autre que vous pourriez ne pas vouloir.)
id myImageURL = [result objectForKey:@"url"];
if (![myImageURL isKindOfClass:[NSString class]]) {
myImageURL = @"";
}