NSDictionary sometimes can contain a key with empty values or even may not contain a key, that we expect to have. This is a very common problem, when you work with server APIs and parse network JSON responses to a NSDictionary. In this post I will describe how to safely work with NSDictionary that may have empty values or may not have a key.
The method objectForKey will return nil, if there is no a key, a key doesn’t exist in a dictionary.
You can’t add nil to a NSDictionary. NSDictionary will throw an NSInvalidArgumentException if you attempt to insert a nil value. You would have to use [NSNull null] instead. NSNull is something called nothing, while nil is simply nothing.
Checks that value for key is not empty.
1 2 |
if (dic[@"key"] != (id)[NSNull null]) { } |
But if a dic doesn’t contain a key, you will enter to the body of a condition dic[@”key”] != (id)[NSNull null].
For example, before taking integerValue from obj, you must be sure, that it is not [NSNull null]:
1 2 3 4 |
id obj = dic[@"key"]; if (obj != (id)[NSNull null]) { cityId = [obj integerValue]; } |
Checks that the key exists, but value for it can still be empty.
1 2 |
if (dic[@"key"] != nil) { } |
So the optimal check while reading NSDictionary is this, where key is “key”
1 2 3 |
id obj = dic[@"key"]; if ((obj != nil) && (obj != (id)[NSNull null])) { } |
You can’t add nil to a NSDictionary. So you have to check, that your object is not nil before adding:
1 2 3 |
if (obj != nil) { NSDictionary *dic = @{@"key":obj}; } |
But you can add [NSNull null]:
1 2 |
id obj = [NSNull null]; NSDictionary *dic = @{@"key":obj}; |
Version of code, where you check if dictionary entry exists and not empty:
1 2 3 4 5 6 7 8 9 10 11 12 |
id obj = dic[@"key"]; if ( obj != nil ) { if ( obj != (id)[NSNull null] ) { // Use obj to get data } else { NSLog(@"Warning! ClassName: key section is empty."); } } else { NSLog(@"Warning! ClassName: key section is not found."); } |
I have created a NSDictionary category that has a method to check if a key exists and value is not empty:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#import "NSDictionary+CheckKey.h" @implementation NSDictionary (CheckKey) - (BOOL)checkKey:(NSString *)key className:(NSString *)className { BOOL success = NO; id obj = self[key]; if ( obj != nil ) { if ( obj != (id)[NSNull null] ) { success = YES; } else { NSLog(@"Warning! %@: %@ section is empty.", className, key); } } else { NSLog(@"Warning! %@: %@ section is not found.", className, key); } return success; } @end |
This is an example, how to use it:
1 2 3 |
if ([dic checkKey:@"key" className:NSStringFromClass(self.class)]) { self.object = dic[@"key"]; } |