预编译宏命令的笔记以及颗粒度Log…

因为想在程序中适当的打印log信息,并且在release的时候不执行任何log的操作,但是NSLog的功能好像不太顺手,自己弄了一个,涉及到一些宏命令的问题,先记录笔记,最后是实现Log的头文件
-------------------------------------------------
关于预编译宏命令的笔记
——————————————————————————
【以下参考自:http://blog.chinaunix.net/uid-22878837-id-2110544.html】
常见宏 ##__VA_ARGS__, __FILE__, __LINE__ 和__FUNCTION__,下面介绍一下这几个宏:
  1)  __VA_ARGS__ 是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持(VC6.0的编译器不支持)。宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错, 你可以试试。
  2) __FILE__ 宏在预编译时会替换成当前的源文件名
  3) __LINE__宏在预编译时会替换成当前的行号
  4) __FUNCTION__宏在预编译时会替换成当前的函数名称
  有了以上这几个宏,特别是有了__VA_ARGS__ ,调试信息的输出就变得灵活多了。

【以下部分转自:http://www.cnblogs.com/morewindows/archive/2011/08/18/2144112.html】

宏中的#的功能是将其后面的宏参数进行字符串化操作(Stringizing operator),简单说就是在它引用的宏变量的左右各加上一个双引号。

如定义好#define STRING(x) #x之后,下面二条语句就等价。

       char *pChar = "hello";

       char *pChar = STRING(hello);

还有一个#@是加单引号(Charizing Operator

#define makechar(x)  #@x

       char ch = makechar(b);char ch = 'b';等价。

 

但有小问题要注意,宏中遇到###时就不会再展开宏中嵌套的宏了。什么意思了?比如使用char *pChar = STRING(__FILE__);虽然__FILE__本身也是一个宏,但编译器不会展开它,所以pChar将指向"__FILE__"而不是你要想的形如"D:\XXX.cpp"的源文件名称。因此要加一个中间转换宏,先将__FILE__解析成"D:\XXX.cpp"字符串。

定义如下所示二个宏:

#define _STRING(x) #x

#define STRING(x) _STRING(x)

再调用下面语句将输出带""的源文件路径

       char* pChar = STRING(__FILE__);

       printf("%s %s\n", pChar, __FILE__);

可以比较下STRING(__FILE__)__FILE__的不同,前将带双引号,后一个没有双引号。

 

再讲下##的功能,它可以拼接符号(Token-pasting operator)。

MSDN上有个例子:

#define paster( n ) printf( "token"#n" = %d\n", token##n )

int token9 = 100;

再调用  paster(9);宏展开后token##n直接合并变成了token9。整个语句变成了

printf( "token""9"" = %d", token9 );

C语言中字符串中的二个相连的双引号会被自动忽略,于是上句等同于

printf("token9 = %d", token9);

即输出token9 = 100

——————————————————————————
NSLog自定义Format的问题
——————————————————————————
【参考:http://blog.csdn.net/tangaowen/article/details/8096624】
在使用宏命令预编的时候发现,形如这样的组合会报错:
NSString* baseFormat = @"Hello %@";
NSString* argsWorld = @"World";
NSLog(baseFormat,argsWorld);
报错:Format string is not a string literal (potentially insecure)
原因:NSLog为了安全,只接受格式化的字符串,因为NSLog底层也是用printf来格式化输出的。
一种解决方案:
NSString* logString = [NSString stringWithFormat:
@"Hello %@", @"World");
NSLog(@"%@",logString);

——————————————————————————————————
自己写的Log头文件KingsLog.h
——————————————————————————————————
使用方式:
因为需要控制在某个文件中输出某个级别的Log信息,所以没有把文件放在pch中,而是在每个需要用log的文档中的开头如下使用:
#define KingsLogActivated//若不想输出当前文件中的Log,则把该定义注释掉
#import "KingsLog.h"
——————————————————————————————————————————
代码
——————————————————————————————————————————
#ifndef ___KingsLog_h
#define ___KingsLog_h

#ifdef KingsLogActivated

#define nsFileString [[NSString stringWithUTF8String:__FILE__] substringFromIndex:1+[[NSString stringWithUTF8String:__FILE__] rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"/"] options:NSBackwardsSearch].location]
#define kingsLogString(logType,format,...) [NSString stringWithFormat:@"\n%s [Line %d in %@]:\n\t%@",logType,__LINE__,nsFileString,[NSString stringWithFormat:format, ##__VA_ARGS__]]
//#define kingsLogString(logType,format,...) [NSString stringWithFormat:@"\n%s [Line %d at %s in %@]:\n\t%@",logType,__LINE__,__FUNCTION__,nsFileString,[NSString stringWithFormat:format, ##__VA_ARGS__]]

//日志分级制度
    //#define DEBUG//XCODE默认有Debug定义,即无论是否定义DEBUG,都会输出Debug
    #define INFO "InfoLog"
    #define WARN "WarnLog"
    #define ERROR "ErrorLog"
    #define FATAL "FatalLog"

    #ifdef DEBUG //DEBUG Level指出细粒度信息事件对调试应用程序是非常有帮助的。
        #define DebugLog(format, ...) NSLog(@"%@",kingsLogString("DebugLog",format,##__VA_ARGS__))
    #else
        #define DebugLog(format, ...)
    #endif

    #ifdef INFO //INFO level表明 消息在粗粒度级别上突出强调应用程序的运行过程。
        #define InfoLog(format, ...) NSLog(@"%@",kingsLogString(INFO,format,##__VA_ARGS__))
    #else
        #define InfoLog(format, ...)
    #endif

    #ifdef WARN //WARN level表明会出现潜在错误的情形。
        #define WarnLog(format, ...) NSLog(@"%@",kingsLogString(WARN,format,##__VA_ARGS__))
    #else
        #define WarnLog(format,...)
    #endif

    #ifdef ERROR //ERROR level指出虽然发生错误事件,但仍然不影响系统的继续运行。
        #define ErrorLog(format, ...) NSLog(@"%@",kingsLogString(ERROR,format,##__VA_ARGS__))
    #else
        #define ErrorLog(format, ...)
    #endif

    #ifdef FATAL //FATAL level指出每个严重的错误事件将会导致应用程序的退出。
        #define FatalLog(format, ...) NSLog(@"%@",kingsLogString(FATAL,format,##__VA_ARGS__))
    #else
        #define FatalLog(format, ...)
    #endif
#else
    #define DebugLog(format, ...)
    #define InfoLog(format, ...)
    #define WarnLog(format,...)
    #define ErrorLog(format, ...)
    #define FatalLog(format, ...)
#endif

#endif
————————————————————
调用方法
————————————————————
WarnLog(@"normalViewController Find keyword: %@",keyWord);

————————————————————————————————
输出效果
————————————————————————————————
2014-03-13 14:00:52.785 kings[808:60b]
InfoLog [Line 103 in NormalScanViewController.m]:
    normalScanViewController Will Appear
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值