在写Objective-C代码的时候,你平时打log是否也一直是简单地调用NSLog来输出信息呢?有时候甚至只是为了验证一下程序到底有没有执行某一块代码,心烦的时候,我甚至会这么打log:
NSLog(@"Fuck the code")
然后如果不小心调完代码后忘了去掉了,以后翻出来的话就冏了。
好吧,进入正题,首先来聊一聊这个东西:_cmd
你肯定知道self吧,_cmd和他很相似。只不过self表示的是正在调用类方法的实例,作用范围是整个类。而_cmd则表示正在被调用的方法,作用范围是该方法内部。_cmd有个显而易见的应用就在于打log上,比如我有如下的宏:
#define METHOD_LOG (NSLog(@"%@\n%s\n%@", \
NSStringFromSelector(_cmd), \
__FILE__, self))
然后我在下面的viewDidLoad方法内调用这个宏:
- (void)viewDidLoad
{
METHOD_LOG;
}
可以得到如下的log信息:
viewDidLoad
/Users/keywind/Downloads/ndfred-coredata-bit-me-3ec4df7/Source/UI/BenchmarkViewController.m
<BenchmarkViewController: 0x6c5ca40>
能够很清晰地显示出当前正在调用的方法。
关于_cmd我还看到有这么用的:
@property (readwrite) id color;
- (id)color;
{
//SomeDictionary defined elsewhere in class
return [SomeDictionary objectForKey:
[NSStringFromSelector(_cmd) capitalize]];
}
- (void)setColor:(id)someObject;
{
//3 means we start from the C in Color
NSString *partial_string;
partial_string = [NSStringFromSelector(_cmd)
substringFromIndex:3];
//SomeDictionary defined elsewhere in class
[SomeDictionary setObject:someObject
forKey:partial_string];
}
这么用的好处就是我根本没有创建color实例变量,我不用去管内存,都由NSDictionary代替管理。对于Objective-C这种动态语言来说,用好运行时也是相当有意义的。
回到上面那个log宏来,这个宏里有个预定义宏__FILE__用来显示当前的文件,可以借助其他一些宏来帮助打log,这里我查到stackoverflow上一则Post,给出了一些比较满意的log宏。这里我就直接偷来用上:
#ifdef DEBUG
# define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define DLog(...)
#endif
// ALog always displays output regardless of the DEBUG setting
#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#ifdef DEBUG
# define ULog(fmt, ...) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"%s\n [Line %d] ", __PRETTY_FUNCTION__, __LINE__] message:[NSString stringWithFormat:fmt, ##__VA_ARGS__] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; [alert show]; }
#else
# define ULog(...)
#endif
DLog宏用来在debug时调用,一到release版本时就不打出log。这也有个好处,就是一半我们在debug时的那些log有时候我们在release时总是忘记删掉,而且在暗地里打大量log是影响程序的性能的。DLog宏避免了这个问题。ALog则不管,始终打log。且来看看log的样式,比如调用
ALog(@"Hello world")
则相应的log信息则是:
-[LibraryController awakeFromNib] [Line 364] Hello world
所调方法,行号,以及自定义消息都有了,这样看起来一目了然。




