Learn Objective-C: A Handy Debugging Tool

During the development of any application, there will be times when you have to track errors in your code. Having the errors be clearly expressed in the Console or in an alert will help with the debugging. As an example, rather than letting your application crash with an exception, it might make sense to log a clear error and defer the fix to a later time.

Because of this, I’ve made a simple little macro that formats the error in a nate way. This is the macro:

  1. #define LOCATION_AS_NSSTRING [NSString stringWithFormat:@"Function: %s\nLine: %d\nFile: %s", __func__, __LINE__, __FILE__]
  2. #define STRING_REPRESENTATION_OF_ERROR(x) [NSString stringWithFormat:@"\n==== ERROR ====\nError %d: %@\nSeverity: %@\n%@", x, x ## _STRING, x ## _SEVERITY, LOCATION_AS_NSSTRING]

It is actually two macros; the former is a “helper” macro and you interact with the latter. The macro works with three other preprocessor declarations. It’ll make the most sense to put this in context:

  1. /******* Severity Levels ******/
  2. #define SEVERITY_NO_ACTION @"No action required"
  3. #define SEVERITY_LOW @"Low"   // Minimal user action to fix OR cannot fix, but doesn't severly affect usability
  4. #define SEVERITY_HIGH @"High" // Extensive user action to fix OR cannot fix, and affects usability somewhat
  5. #define SEVERITY_CRITICAL @"Critical" // Crashers; cannot recover from issue
  6. #define SEVERITY_UNKNOWN @"Unknown"   // Not enough information to decide
  7.  
  8. #define ERROR_CODE_1 1  // No sections defined for library
  9. #define ERROR_CODE_1_STRING @"No sections defined for library browser. Returning 1"
  10. #define ERROR_CODE_1_SEVERITY SEVERITY_NO_ACTION
  11.  
  12. // … Some code later …
  13. NSLog(@"%@", STRING_REPRESENTATION_OF_ERROR(ERROR_CODE_1));

This code example will output the following:

  1. ==== ERROR ====
  2. Error 1: No sections defined for library browser. Returning 1
  3. Severity: No action required
  4. Function: <ContainingMethod>
  5. Line: <SomeLineNumberOfCalling>
  6. File: <ContainingFile>

So how does this work? It’s actually rather simple. You pass in the error code listing, and the preprocessor “assigns” this value to the “variable” x. Then it uses that variable in the standard NSString method call. It first “plugs in” the value of x, then combines the full token (remember that you pass in the entire token, ERRORCODE1, so that gets combined and forms ERRORCODE1 ## STRING, which gets joined into ERRORCODE1STRING). It then does the same thing with SEVERITY token, resulting in ERRORCODE1SEVERITY. Finally, it plugs in the results from the other macro, LOCATIONASNSSTRING, which in turn calls three built-in macros (funcLINE, and FILE), which return the calling function, line, and file is C-style strings.

So really, it’s quite simple. There are just a lot of macros involved, and it really becomes quite useful. As an example, you could use this to show a meaningful error to users with an alert, if necessary.

This post is part of the Learn Objective-C in 24 Days course.

Author: Feifan Zhou