A very trivial, yet often overlooked property of NSError is the localizedDescription and localizedRecoverySuggestion property. Most Objective-C frameworks whether Apple’s own SDK or third party frameworks use a NSError out reference to communicate errors to the caller.

To give you an example, take the NSJSONSerialization class.
Parsing JSON from a data (say response data from a NSURLConnection) can fail if the JSON is malformed.

id jsonResult = [NSJSONSerialization JSONObjectWithData:myJsonData options:0 error:&error];

When such JSON parsing errors occur, the NSJSONSerialization class fills in the error object that you pass by reference.

A wrong way to handle errors like this is

if(!jsonResult) {
 
[[[UIAlertView alloc] 
    initWithTitle:NSLocalizedString(@"JSON Parsing Failed", @"") 
    message:NSLocalizedString(@"JSON is malformed", @"")
    delegate:nil
    cancelButtonTitle:NSLocalizedString(@"Dismiss", @"")
    otherButtonTitles: nil] show];
 
}

The above code is not right for the following reasons,
1. You are not communicating the real error that occurred.
2. You are assuming that malformed JSON is the only error that could happen.
3. You are not communicating the location (line number) where the error occurred.

A more appropriate way is to probe the NSError object for information on what really went wrong. The userInfo object of NSError contains enough information that is required to show a more meaningful message to the user. It contains the exact reason for the error in the device’s localized language among a wealth of other information. I wrote a category on UIAlertView, a while ago to show a alert view based on a NSError.

+(UIAlertView*) showWithError:(NSError*) error {
 
    UIAlertView *alert = [[UIAlertView alloc] 
    initWithTitle:[error localizedDescription]
    message:[error localizedRecoverySuggestion]
    delegate:nil
    cancelButtonTitle:NSLocalizedString(@"Dismiss", @"")
        otherButtonTitles:nil];
 
    [alert show];
    return alert;
}

Your calling code now looks like

if(!jsonResult) {
 
    [UIAlertView showWithError:error];
}

Using this, you have in fact reduced clutter in your error handling code and added clarity. Killed two birds with one stone!

If you love this code snippet, you should checkout MKNetworkKit. This snippet is in fact a part of MKNetworkKit. MKNetworkKit is a clean, fast ARC compatible networking framework. Give it a try and let me know.

Update: Error checking is now done by checking the return value and not the error object. Read this for more info.
http://weblog.bignerdranch.com/360-an-nserror-error/

Thanks Glenn Chiu


Mugunth

Follow me on Twitter

  • Jmstone617

    You should update your code snippet that uses your UIAlertView category to be checking the json object and not the error.

    • MugunthKumar

      Thanks for the heads up.
      Done

  • James

    and what about @try { } @catch { } block ? is it good ?

  • Tom

    Just a note for non-ARC apps:

    I think you’d want an [alert release] after the [alert show] or call autorelease on the newly created alert;

    Otherwise set a delegate on the it and in the delegates callback release the alert.

  • Isuru

    This is a very useful article. Thank you for sharing your knowledge on this mostly overlooked topic