开发者

Using macro in Objective-C to log function name and line number

I have the following simplified code example:

// in .h file
// define a macro for partial method
#define debugWithMsg context:(CFStringRef)__FUNCTION__ lineNumber:__LINE__ debug:

@interface MyLogger : NSObject {
  ...
}

- (void) context:(CFStringRef)function 
      lineNumber:(int)line 
           debug:(NSString*)messageFormat, ...;
@end

I use this method in other classes to print debug messages to XCode console. Here is an example I test my debug method(in MyViewController class with a table view):

- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
  ...
  // myLogger is an instance of MyLogger.
  [myLogger debugWithMsg@"something for %@", @"testing!"];
  ...
}
...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  ...
  [myLogger debugWithMsg@"something for %@", @"another testing!"];
  ...
}

The above example works well; however, for me, it does not look like a standard C/C++ or ObjC syntax. The reason I need to use this macro is that I would like to pass the first two arguments as "constants" to the method. Actually, those two arguments are also macros: __FUNCTION__ being a C++ macro, and __LINE__ being a C standard macro. Those two special macros would be dynamically mapped to a string of the function and a line number where the method is called. For example the above debug method call prints a msg in XCode console like this:

[timestamp] -[MyViewControll开发者_如何学Goer tableView:numberOfRowsInSection:] line:107 - something for testing!
...
[timestamp] -[MyViewController tableView:cellForRowAtIndexPath:] line:124 - something for another testing!

The MyLogger class is mainly for my internal use. Is there any other better practice to get the same result? Or is there any problem with this implementation?

I am thinking to define my macro in the same way as NSLog(fmt, ...), which is a macro as well:

MyDebugLog(instance, fmt, ....)

where instance is an instance of MyLogger, and fmt, ... are format string and var list. This is my trial definition of the macro:

#define MyDebugLog(logger, fmt, ...) \
  [logger, context:(CFStringRef)__FUNCTION__ lineNumber:__LINE__ \
   debug:fmt, ## _VA_ARGS__]

I got compiling error saying "'context' undeclared" in my code where the macro is used:

- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
  ...
  // myLogger is an instance of MyLogger.
  MyDebugLog(myLogger, @"something for %@", @"testing!"); // compiling error!
  ...
}

Not sure what's wrong in my definition. Any suggestions?


This is what I use.

#define SFLog(message, ...) NSLog((@"SFLOG: %s [Line %d] " message), __PRETTY_FUNCTION__, __LINE__, ## __VA_ARGS__)

You use it exactly like SFLog(@"Some var %f", myFloat); except it prepends the 'SFLog' (I also use 'SFError') and the __PRETTY_FUNCTION__ macros.


[EDIT]

I found the SO post where I got this. It's over here.


[Edit]

Commenter Jonathan Leffler points out below that the macro can be defined without the ##. The ## is purely a GCC thing, and doesn't conform to C99 standard. ## also works with LLVM/Clang 1.5 (XCode 3.2.4) as well as compiler settings for -std=c99 and -std=gnu99. Just understand that there are some limitations for the macro if it doesn't work as expected.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜