宏定义输出(NSLog)
前言:
我们在发布App的时候,🍎要求我们取消所有的NSLog,大概是因为:
1)输出日志是会大量损耗系统性能。
2)输出的信息很容易会被截取到,导致信息不安全。
如果一行一行地去注释掉NSLog,显然不是一个明智的选择。因此我们可以使用宏去自定义NSLog输出。
先说一点关于NSLog使用的格式问题,我是今天实验过后才是到,也许你之前就已经知道,这一点有助于理解下文中宏定义中的格式问题:
通常使用NSLog
我是这么用的
NSLog(@"%@", @"大家好"); // 一个参数
NSLog(@"%@ %@", @"大家好", @"才是真的好"); // 两个参数
NSLog(@"%@ %@ %@", @"大家好", @"才是真的好", @"XX真好!"); // 三个参数
打印结果:
2016-05-27 11:53:05.045 ViewController[4524:111041] 大家好
2016-05-27 11:53:05.045 ViewController[4524:111041] 大家好 才是真的好
2016-05-27 11:53:05.045 ViewController[4524:111041] 大家好 才是真的好 XX真好!
但是,今天发现NSLog中的格式可以是下面这样:
NSLog(@"%@" "%@", @"大家好", @"才是真的好"); // 两个参数
NSLog(@"%@" "%@" "%@", @"大家好", @"才是真的好", @"XX真好!"); // 三个参数
打印结果:
2016-05-27 11:53:05.046 ViewController[4524:111041] 大家好才是真的好
2016-05-27 11:53:05.046 ViewController[4524:111041] 大家好才是真的好XX真好!
你看明白了吗?(__)
1)简单的NSLog
我们在调试程序的时候,往往需要输出一些日志信息,用到NSLog函数,当我们准备发布程序,需要注释掉NSLog代码,这个时候往往会定义一个宏,在调试的时候,会输出日志,在Release正式版本的时候,会关闭日志输出。代码如下:
#ifdef DEBUG
#define GCLog(fmt, ...) NSLog((fmt), ##__VA_ARGS__);
#else
#define GCLog(...);
上面这段代码,是最常见的自定义NSLog的方式,但是上面的这段代码有一定的局限性,就是日志信息不够明确,如果在调试窗口打印N多信息的话,我么想知道某条日志信息是哪个类、哪一行打印的怎么办呢?
2)打印详细的日志信息
#ifdef DEBUG
# define DLog(fmt, ...) NSLog((@"\n[File:%s]\n" "[Function:%s]\n" "[Line:%d] \n" fmt), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define DLog(...);
#endif
我们下面调用这个自定义的宏:
- (void)viewDidLoad {
DLog(@"%@", @"你好")
}
打印结果如下:
2016-05-27 11:23:36.089 LogisticsDriver[3893:90262]
[File:/Users/ZZZ/Documents/SVN/LogDemo/LogDemo/ViewController.m]
[Function:-[ViewController viewDidLoad]]
[Line:26]
你好
3)参数解释
-
__VA_ARGS__ 是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持(VC6.0的编译器不支持)。宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错, 你可以试试。
-
__FILE__ 宏在预编译时会替换成当前的源文件名
-
__LINE__宏在预编译时会替换成当前的行号
-
__FUNCTION__宏在预编译时会替换成当前的函数名称
有了以上这几个宏,特别是有了__VA_ARGS__ ,调试信息的输出就变得灵活多了。- VA_ARGS 是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持(VC6.0的编译器不支持)。宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错, 你可以试试。
- FILE 宏在预编译时会替换成当前的源文件名
- LINE宏在预编译时会替换成当前的行号
-
FUNCTION宏在预编译时会替换成当前的函数名称
有了以上这几个宏,特别是有了VA_ARGS ,调试信息的输出就变得灵活多了。
4)参考
http://www.cnblogs.com/GarveyCalvin/p/4157553.html
http://blog.csdn.net/laomai/article/details/276274
http://stackoverflow.com/questions/21873616/how-to-use-va-args-properly