Monday, February 16, 2009

A Debug Macro for Xcode

* Updated on 28 November 2011 for Xcode 4.2

I am a newcomer to the Xcode and I decided to check the debug means. Basically, I was looking for a macro to dump line number, file name and function name along with some output. However, I found only some "simple" debug classes. I think debug output should be done by macros. I checked the Apple documentation and found an interesting topic: Variadic Macros. They are introduced by the C99 standard. After a few attempts I decided that the following macro is good enough for me:

//
//  dbg.h
//
//  Created by oguz.kupusoglu@gmail.com on 15/2/2009.
//  Copyright 2009 Oguz Kupusoglu. All rights reserved.
//

#ifdef DEBUG
    #define DBG(format, ...)                   NSLog(@"%d,%s,"format,__LINE__,__FUNCTION__,##__VA_ARGS__);
    #define DBG_CALLED                         DBG("called")
#else
    #define DBG(format, ...)
    #define DBG_CALLED
#endif

#define LOG(format, ...)                       NSLog(@"%d,%s,"format,__LINE__,__FUNCTION__,##__VA_ARGS__);
#define LOG_CALLED                             LOG("called")   

Note that DBG_CALLED is a helper define which is useful for following the callstack. I ignored the file name, i.e. __FILE__, as the method name being in the [class method] format gives a hint of the file in question due to naming files after the class names convention. Certainly one can add __FILE__ at the expense of extra overhead. Sample usage and output as received from the Console which is accessed from the "View/Debug Area/Activate Console" option of the Xcode are below:

-(void) viewWillAppear:(BOOL)animated
{
    DBG_CALLED
    
    DBG("view frame\n"
        "origin x:|%.0f|  y:|%.0f|\n"
        "width:|%.0f|  height:|%.0f|\n",
        self.view.frame.origin.x, self.view.frame.origin.y,
        self.view.frame.size.width, self.view.frame.size.height)   
       
    DBG("year:|%d|", 2009)
   
    DBG("updated")
       
    [super viewWillAppear:animated];
}

...] 69,-[MyViewController viewWillAppear:],called
...] 75,-[MyViewController  viewWillAppear:],view frame
origin x:|0|  y:|20|
width:|768|  height:|1004|
...] 77,-[MyViewController viewWillAppear:],year:|2009|
...] 79,-[MyViewController viewWillAppear:],updated

Note that the DEBUG define is set via the "PROJECT/Build Settings" option. Go to "... Preprocessing" section and add the define "DEBUG" to the "Debug" subsection.

Finally, I think "Product/Generate Output\Generate Preprocessed File" is a good option as it gives the preprocessor output of the selected file. For example the above DBG() macros are expanded as below:

-(void) viewWillAppear:(BOOL)animated
{
    NSLog(@"%d,%s,""called",69,__FUNCTION__);

    NSLog(@"%d,%s,""view frame\n" "origin x:|%.0f|  y:|%.0f|\n" "width:|%.0f|  height:|%.0f|\n",75,__FUNCTION__, self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height);





    NSLog(@"%d,%s,""year:|%d|",77,__FUNCTION__, 2009);

    NSLog(@"%d,%s,""updated",79,__FUNCTION__);

    [super viewWillAppear:animated];
}

Note that when there is no variable argument, "##" removes the trailing comma! Just excellent...

1 comment:

M.Burak Alkan said...

Heya,

I think I know this type of macro from somewhere :)
btw this variadic macro thing is life saver, I'm happy to learn this in the beginning of my career[thanks to you actually]