这源于我搜索NSLog()
的智能变体。 BetterLog()
的一个关键特性是NSLog()
替换为发布和分发版本编译为空。建议的解决方案(参见例如Is it true that one should not use NSLog() on production code?)定义一个预处理器符号来控制BetterLog()
的定义,具体取决于构建的类型。典型地:
#ifdef DEBUG_MODE
#define DebugLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DebugLog( s, ... )
#endif
其中DEBUG_MODE
将被定义为仅用于调试版本的预处理器符号。
但是,在许多情况下,即当使用中间变量构建日志记录语句时,结果是未使用变量的编译器警告。这是一个例子:
if (error) {
NSString *titleString = @"Error downloading thumbnail, will rebuild it";
NSString *messageString = [error localizedDescription];
NSString *moreString = [error localizedFailureReason] ? [error localizedFailureReason] : NSLocalizedString(@"Check the URL.", nil);
BetterLog(@"%@: %@. %@", titleString, messageString, moreString);
} // silently ignoring *this* error is OK.
这里所有三个字符串都会产生编译器警告。而且我讨厌编译器警告。
当然,如果不以某种方式有条件地包括变量声明本身,就无法避免。我做了以下尝试,但它不起作用:
而不是仅仅在调试模式下定义DEBUG_MODE
,我一直定义它,在调试模式下值为1,在发布模式下值为0。
然后我尝试利用编译器死代码剥离优化:
if (DEBUG_MODE && error) {
// snip
}
代码正常:它在发布模式下被正确删除。然而,编译器仍会发出未使用的变量警告。
所以问题是:是否有可能做得比丑陋更好:
#if DEBUG_MODE
if (error) {
// snip
}
#endif
答案 0 :(得分:1)
一种选择是:
#define BetterLog(...) do { (void)(__VA_ARGS__); } while (0)
这样做的好处是,如果你到达BetterLog(),它的参数的任何副作用都将被评估,并且它是一个干净的语句所以它不是写if (x) BetterLog(@"%@", x);
的错误(这将破坏下一个语句使用你的宏。)
就个人而言,我更喜欢使用“丑陋”的预处理器方法,因为它明确地排除了调试代码。