Tag: NSNull

  • How to safely work with NSDictionary that may have empty values or may not have a key

    Dictionary_2x

    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.

    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]:

    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.

    if (dic[@"key"] != nil) {
    }
    

    So the optimal check while reading NSDictionary is this, where key is “key”

    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:

    if (obj != nil) {
       NSDictionary *dic = @{@"key":obj};
    }
    

    But you can add [NSNull null]:

    id obj = [NSNull null];
    NSDictionary *dic = @{@"key":obj};
    

    Version of code, where you check if dictionary entry exists and not empty:

    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:

    #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:

    if ([dic checkKey:@"key" className:NSStringFromClass(self.class)]) {
        self.object = dic[@"key"];
    }