2

这来自我对NSLog(). 的一个关键特性BetterLog()是,NSLog()对于发布和分发构建,替换编译为空。建议的解决方案(例如,请参阅是否真的不应该在生产代码上使用 NSLog()?)是定义一个预处理器符号来控制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

whereDEBUG_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
4

1 回答 1

1

一种选择是:

#define BetterLog(...) do { (void)(__VA_ARGS__); } while (0)

这样做的好处是,如果您到达 BetterLog(),将评估其参数的任何副作用,并且它是一个干净的语句,因此它不是编写错误if (x) BetterLog(@"%@", x);(这会破坏使用您的宏的下一条语句)。

就个人而言,我更喜欢使用“丑陋”的预处理器方法,因为它明确排除了调试代码。

于 2010-09-13T15:14:49.167 回答