iOS How to check if valueForKey exist or not? - ios

I have another question about checking the existence of valueForKey.
Here's my code:
id _jsonId = [NSJSONSerialization JSONObjectWithData:[_json dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&_error];
Monday = [[NSMutableArray alloc] init];
if ([_jsonId valueForKey:#"Mon"]!= Nil) {
_keyMon = [_jsonId valueForKey:#"Mon"];
[Monday addObject:#"Monday"];
for (int i=0; i<5; i++) {
if ([_keyMon objectAtIndex:i]!=[NSNull null]) {
[Monday addObject:[_keyMon objectAtIndex:i]];
}
}
} else {
[_keyTues addObject:#"No Class For Today"];
[Monday addObject:[_keyMon objectAtIndex:1]];
}
The idea is, if the _jsonId valueForKey came back nothing, I can add this NSStringaddObject:#"No Class For Today incase XCode tells me that:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
like it has been telling me now. Anyone have any solution?
I tried if ([_jsonId valueForKey:#"Mon"]!= Nil) didn't work.
I tried if ([_jsonId valueForKey:#"Mon"]!= nil) didn't work.
I tried if ([_jsonId valueForKey:#"Mon"]!= (id)[NSNull null]) didn't work.
I tried if ([_jsonId valueForKey:#"Mon"]!= [NSNull null) didn't work.
I know that _jsonId valueForKey is came back as a pointer, but I have no idea how to check if the pointer is null(or nil in Objective-C if I'm correct). Please help me.
UPDATE:
I have tried using objectForKey and here is a code(_jsonId objectForKey is nil, that I know to try testing the code)
if (_jsonId[#"Sun"]== nil) {
[_keySun addObject:#"No Class For Today"];
[Monday addObject:[_keySun objectAtIndex:1]];
}
else{
_keySun = [_jsonId objectForKey:#"Sun"];
[Monday addObject:#"Sunday"];
for (int i=0; i<5; i++) {
if ([_keySun objectAtIndex:i]!=nil) {
[Monday addObject:[_keySun objectAtIndex:i]];
}
}
}
Still, XCode telling me that I'm add a nil into NSArray.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
This is driving me crazy...

_jsonId as defined by:
id _jsonId = [NSJSONSerialization JSONObjectWithData:[_json dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&_error];
... will be either an array or a dictionary. Based on your code I think you're assuming that it's always a dictionary. So you probably want to add:
if (![_jsonId isKindOfClass:[NSDictionary class]]) ...
You then want to know what's in a dictionary, if anything. So use objectForKey:. Or, better, just _jsonId[#"Mon"]. You'll get an object or you'll get nil.
valueForKey: is a completely different mechanism, key-value coding. It is defined on NSObject so inherited by NSDictionary as well as just about everything else. It is defined to raise an exception for an unknown key. Since it raises an exception instead of returning a result, your attempts to compare a result are ineffective.

I think I figured it out. Let's look at the code:
if (_jsonId[#"Sun"]== nil) {
[_keySun addObject:#"No Class For Today"];
[Monday addObject:[_keySun objectAtIndex:1]];
}
else {
_keySun = [_jsonId objectForKey:#"Sun"];
...
If there is an object for the key "Sun" then you store it into _keySun. If there is no object, then you store nothing into _keySun. _keySun will be nil. You send an addObject message to _keySun - but any message sent to a nil object does nothing. You then call [_keySun objectAtIndex:1]. Again, sending a message to a nil object does nothing, and returns nil, which is why you add nil to the Monday object and get a crash.
If you had set _keySun to an empty NSMutableArray, you would have crashed for another reason: You try to add one object. You can read that one object with objectAtIndex:0. But to read objectAtIndex:1 you need two objects in the array.
BTW. You will get [NSNull null] from the JSON parser if the JSON document that you are reading contains an explicit null. So if your JSON contains "Sun": null then objectForKey:#"Sun" will give [NSNull null]. If your JSON doesn't contain the key "Sun" at all, objectForKey:#"Sun" will give nil.

Related

IOS: How to check json object is not null

I am getting an error with the following code when some json is null even though I am trying to check that first:
Edit: Preceding Code:
NSData* data = [NSData dataWithContentsOfURL: kItemsURL];
//previous line grabed data from api.
if (data) {
[self performSelectorOnMainThread:#selector(fetchData:) withObject:data waitUntilDone:YES];
}
- (void)fetchData:(NSData *)jsonFeed {
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:jsonFeed options:kNilOptions error:&error];
//Original code provided
if (![[json objectForKey:#"items"] isKindOfClass:[NSNull class]]) {
NSLog(#"got here");
NSLog(#"json%#",json);
latestItems = [[json objectForKey:#"items"]mutableCopy];
}
Is there a better way to check Json is not null?
Here is error output:
2016-05-03 13:05:43.820 testApp[407:60b] got here
2016-05-03 13:05:43.821 testApp[407:60b] json{
items = "<null>";
}
NSNull mutableCopyWithZone:]: unrecognized selector sent to instance 0x3ac26a70
2016-05-03 13:05:43.825 ChallengeU[407:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull mutableCopyWithZone:]: unrecognized selector sent to instance 0x3ac26a70'
if (![json[#"items"] isEqual:[NSNull null]]) {
//do your stuff in here
}
I don't know what's wrong with your code, but the easiest way to check for a JSON null value if you are sure that json is a dictionary is:
if (json [#"items"] != [NSNull null]) { ... }
[NSNull null] always returns the same instance of NSNull. There is never more than one instance of NSNull, so you can actually use pointer comparison to check whether an object is an NSNull instance.
if (json && [json isKindOfClass:[NSDictionary class]]) {
//your code here
} else {
//invalid json
}
if ([json objectForKey:#"items"] != nil) {
NSLog(#"got here");
NSLog(#"json%#",json);
latestItems = [[json objectForKey:#"items"]mutableCopy];
}
NULL or nil is not a class, but a convention. The memory adress 0 is the point where a cpu starts to execute code during cold start. Therefore no object can have this address in memory.
By the book should the json not have the key #"items" if the value of #"items" is NULL. The missing key indicates a NULL value.

How to check NSDictionary for Key Value pairs without making it crash? [duplicate]

This question already has answers here:
How can I debug 'unrecognized selector sent to instance' error
(9 answers)
Closed 7 years ago.
I am currently doing something like this
NSDictionary *imageDataDictionary = nil;
imageDataDictionary = (NSDictionary *)metadataItem.value;
if(imageDataDictionary != nil)
{
if ([imageDataDictionary objectForKey:#"data"] != nil) <---Crashes
{
}
}
The app crashes on
if ([imageDataDictionary objectForKey:#"data"] != nil)
because it has 0 key value pairs.
I wanted to know what would the right way be to check if a NSDictionary is valid and if it has any key value pairs
This is the messages
2015-04-19 15:56:37.255 MBlast[61278:2115186] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFData objectForKey:]: unrecognized selector sent to instance 0x7c16a7e0'
You are casting an object of unspecified type to an NSDictionary. That tell the compiler "trust me, this is a dictionary."
If the object is NOT a dictionary, you'll crash. That is almost certainly what's going on here. Add some error checking:
if (![mediadataItem.value isKindOfClass: [NSDictionary class]])
return; //The object isn't a dictionary. Bail.
NSDictionary *imageDataDictionary;
imageDataDictionary = (NSDictionary *)metadataItem.value;
if(imageDataDictionary != nil)
{
if ([imageDataDictionary objectForKey:#"data"] != nil) <---Crashes
{
}
}

app is crashing on second run through of loop with nsnull count

I have a loop that works fine the first time through but the second time through the loop I get:
-[NSNull count]: unrecognized selector sent to instance 0x3a094a70
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull count]: unrecognized selector sent to instance 0x3a094a70'
Here is the part in my code where I know it is crashing (the last line):
...
NSLog(#"dict::%#",dictForPost);
// collect the photo urls in an array
photosInDict = [NSArray array];
// photos is an array of dictionaries in the dictionary
photosInDict = dictForPost[#"photos"];
if (photosInDict.count) {
....
I know that when photosInDict doesnt have pictures in the dic it crashes but I dont get why since I initiated the array above it.
photosInDict = dictForPost[#"photos"]
replaces the object previously allocated and stored in photosInDict.
Therefore it does not make sense to allocate the array before. Just
NSArray * photosInDict = dictForPost[#"photos"];
and then check
if ([photosInDict isKindOfClass:[NSArray class]]) {
// Yes, it is an array. Do something with it.
if ([photosInDict count]) {
...
}
}
The result of dictForPost[#"photos"]; is giving you an NSNull object, not an array.
One option would be this:
NSLog(#"dict::%#",dictForPost);
// collect the photo urls in an array
// photos is an array of dictionaries in the dictionary
photosInDict = dictForPost[#"photos"];
if ([photosInDict isKindOfClass:[NSArray class]] && photosInDict.count) {
The line:
photosInDict = [NSArray array];
is pointless and should be removed.
You initialize photosInDict with an empty array, but then you overwrite it with the dictionary's value for "photos", which just happen to be NSNull. You need to check why your dictionary does not have an array for that key.
If the value can be NSNull depending on the situation, you must check whether it is an array or not before trying to count or taking some other action.

__NSCFConstantString objectForKey unrecognized selector sent to instance error

I basically get this error
'NSInvalidArgumentException', reason: '-[__NSCFConstantString objectForKey:]: unrecognized selector sent to instance 0x581f0'
on my program. I think it refers to this call I make,
if (data != nil) {
if([data objectForKey:#"username"]){
// NSArray *check= [[NSArray alloc]init];
//check=[data allValues];
[dict setObject:[data allValues] forKey:#"args"];
}else{
[dict setObject:[NSArray arrayWithObject:data] forKey:#"args"];
}
at the setObject:[data allValues]. I don't know why it gives that error but data is an NSDictionary and I'm getting all the values and placing it in an array.
Is the error happening here:
if([data objectForKey:#"username"]){
I assume so, as that is the only place objectForKey seems to be called. You are calling it on a variable called 'data', which i'm guessing simply is not a dictionary. You should NSLog its type to see.

__NSCFString objectForKeyedSubscript: exception

I take datas from server. My app work fine in Sinulator and test device iPhone 4s, but one man have problem on iPod 4. He get exception:
-[__NSCFString objectForKeyedSubscript:]: unrecognized selector sent to instance 0x1d263a20
I cann't use this device so I write code to know where crash was.
if (![dictionaryRest[#"compliments"] isEqual:[NSNull null]]) {
NSMutableArray *array = [NSMutableArray new];
NSMutableArray *firstArray = [NSMutableArray new];
for (NSDictionary *dic in dictionaryRest[#"compliments"]) {
Compliment *compl = [Compliment new];
if (![dic[#"ID_promotions"] isEqual:[NSNull null]])
compl.ID = [dic[#"ID_promotions"] integerValue];
So in last 2 strings this exception was. What the reason of this? So I understand that I need use
if ([dict objectForKey:[#"compliments"])
instead
if (![dict[#"compliments"] isEqual:[NSNull null]])
and in all another cases.
I test now and I have in my dictionary for ID:
You have an NSString instance in your dictionary where you expect a dictionary.
Note that your "use this instead of that" has nothing to do with the problem.
-objectForKeyedSubscript: is an instance method on NSDictionary object.
__NSCFString objectForKeyedSubscript: exception indicates that the method -objectForKeyedSubscript is somehow getting called on some NSString object.
So basically you just have to properly check for the class of the object before you can safely assume that it is actually dictionary.
if([dic isKindOfClass:[NSDictionary class]])
{
id obj = dic[#"key"];
}

Resources