Check Your Error Param!

This is a pretty elementary topic, but one of the most common problems I see on StackOverflow goes like this:

user12345: My code doesn’t work and I don’t know why! ┬áIt looks like this:

id result = [NSSomeFoundationClass getSomeData:@"some input" options:0 error:nil];
if (result == nil) {
    NSLog(@"WTF? Where's my data?!");
}

These posts get quickly down-voted and a backlog of comments that tend towards the shaming side forms. So please, new iOS and OS X developers, if there is an (NSError *) error parameter for the function you’re calling, for the love of all that is good, check this value! Nine times out of ten it will tell you exactly why the call is failing, eg:

NSError * error = nil;
id result = [NSSomeFoundationClass getSomeData:@"some input" options:0 error:&error];
if (result == nil) {
    NSLog(@"Oops, getSomeData failed with error: %@ (userInfo: %@)", [error localizedDescription], [error userInfo]);
}

If you’re lucky, a helpful message like this one will appear in the console:

Oops, getSomeData failed with error: You passed an invalid parameter! (userInfo: { NSProTip = "Go read the docs to understand what this error means and how to fix your code!" })

And if the foundation method you’re calling doesn’t have an error param, double check the docs. Many methods have an overloaded version which takes more options and provides an error param. Use these methods instead to gain more control over how the method functions, and learn about why it may fail. For example, NSData has several such methods:

+ (id)dataWithContentsOfURL:(NSURL *)url;
+ (id)dataWithContentsOfURL:(NSURL *)url options:(NSDataReadingOptions)readOptionsMask error:(NSError **)errorPtr;
+ (id)dataWithContentsOfFile:(NSString *)path;
+ (id)dataWithContentsOfFile:(NSString *)path options:(NSDataReadingOptions)readOptionsMask error:(NSError **)errorPtr;

Along these same lines, often when your app crashes the OS will throw an exception. This, like an NSError, will give you a clue as to what’s wrong. If you go into the debugger and set an exception breakpoint, then the debugger will even halt where the exception is thrown–which is very helpful for tracking down the problem in your code.