Cocoaworks

iOS development and startups

Making NSNull behave like nil

Updated May 7, 2013 after feedback from one of the ObjC runtime developers. Thanks Andy!

When parsing JSON data from a server, the resulting NSArrays and NSDictionaries can contain NSNull instances in cases where the JSON parser received an emtpy string from the server.

NSNull is used as a placeholder for an empty item in array ~~(since NSArrays are nil-terminated, you can’t insert a nil into an array)~~. Update: NSArray isn’t nil terminated, it just not allowed to put nil in them by design. Unfortunately, NSNull doesn’t behave like nil.

// How nil behaves

NSString *aString = nil;
[aString  length]; // valid    

// NSNull behaves differently

NSArray *anArray  = @ [@"one", [NSNull null], @"three"];
for (NSString *string in anArray) {        
    NSLog(@"%i", [string length]); 
    // throws an 'unrecognized selector' exception on second element
}    

Usually, you will want to sanitize the server data before using it. For quick prototypes and hackathons I found it faster to make NSNull behave like nil and ignoring method calls it hasn’t implemented.

There are macros and protocols. I created a very simple category on NSNull that simply sends all messages NSNull receives to unknown methods to nil. Simply add the NSNull+behave.m file to your project (there is no need for a header file), make sure the file is added to Project->Target->Build Phases->Compile Sources and enjoy your hackathon.

Update: While the presented solution works well for NSNull occurences in NSArrays, the solution doesn’t work well if the calling method expects scalar types, because the return value is not always 0. On Intel 32-bit if the method returns a double, messaging nil will return some random floating point number. On ARM and Intel 64-bit architectures, it should work as expected.


Comments