【问题标题】:Objective-C: Removing NSLog calls from 'Distribution'/production builds?Objective-C:从“分发”/生产版本中删除 NSLog 调用?
【发布时间】:2012-08-26 23:38:20
【问题描述】:

更新:

更多信息在这里:

Is it true that one should not use NSLog() on production code?

~~~~~~~~~~~~~~~~~~~~~~~~~~~

情况

我有一些非常漂亮的 NSLog 调用,用于调试应用程序中更复杂的部分。但是,我最近才知道这些会影响运行时性能!

目标

我想在我没有在 Xcode 中实际执行 Product > Run(又名 command-R)的任何运行期间删除我的 NSLog 调用 - 特别是在这个东西部署在 App Store 上的情况下,而且当我与 Xcode 断开连接时正在运行应用程序(即在街上走时只需点击图标)。

建议的解决方案?

假设我已经创建了一个 VIEW_DEBUG 的预处理器宏,那么在我上面描述的情况下,以下实现是否会有效地从执行中删除 NSLog 调用?

    <bunch of code>

#ifdef VIEW_DEBUG
    NSLog(@"really complex logs entries");
#endif

    <even more code>

这对我来说很难“测试”,所以我想我会吸引更有经验的人。 :)

Xcode 设置(供参考)

【问题讨论】:

  • 我不知道,这行得通吗? #define NSLog //

标签: objective-c ios ios5


【解决方案1】:

一个常见的解决方案是将以下代码放在您的前缀文件中(或者您可以创建一个专用类并根据需要#include它):

#ifdef DEBUG    
#define DebugLog(...) NSLog(__VA_ARGS__)
#else
#define DebugLog(...) while(0)
#endif

Xcode 在执行调试构建时已经为您定义了 DEBUG(如您的屏幕截图所示)。 VA_ARGS 是在 C99 中引入的一种创建 variadic macros 的方法。 do/while 确保 DebugLog 即使它不做任何事情也具有相同的净句法效果——不用担心无意义的循环,优化器会为你删除它。

那么您可以像使用NSLog 一样使用DebugLog。这将完全按照您对 VIEW_DEBUG 的建议进行,但您不必复制和粘贴 #ifdef 条件一千次。

【讨论】:

  • #define DebugLog(...) NSLog(VA_ARGS) 也可以。此外,GCC 或 LLVM 不需要 do {} while(0),#define DebugLog(...) 可以正常工作。
  • 固定标记,我对此不以为然:#define DebugLog(...) NSLog(__VA_ARGS__)
  • 感谢两位评论者(尽管我不被允许@两者)——这就是我盲目地复制和粘贴我打开的一个历史悠久的项目的结果。已在船上进行更正,我已将其标记为社区 wiki,因为现在声称拥有答案的所有权并不是很准确。
  • @Tommy & Crew - 新的宏,所以只是为了确认我理解:这些#define 调用正在创建一个名为DebugLog(...) 的新宏(但它可以被命名为任何东西,对吧?) ... 代表我的输入。因此,如果我编码DebugLog(@"test!"),在调试模式下它将换出NSLog(@"test!"),而在非调试模式下,它将换出while(0) 为我所有的NSLogs - 对吗? (或者,根据 MrAnonymous,我什至需要 while(0) 吗?)——此外,当我的手机与 Xcode 断开连接但我正在运行“开发”构建时,DEBUG 是否会“开启​​”?
  • @toblerpwn 差不多了——你会得到 DebugLog(或任何你想叫它的名字),它的行为与你在定义 DEBUG 时输入的 NSLog 完全相同,但就像你输入的一样while(0) 或者其他什么都没有。它仅取决于构建的类型,而不取决于您的设备是否已绑定,但会阻止您使用日志发布,并且无论如何您都无法准确评估开发构建的发布性能 - 这就是为什么当您使用 Instruments 进行分析时例如,它会自动进行发布构建。
【解决方案2】:

我总是在我的代码中使用DLog,效果很好。

// DLog is almost a drop-in replacement for NSLog
// DLog();
// DLog(@"here");
// DLog(@"value: %d", x);
// Unfortunately this doesn't work DLog(aStringVariable); you have to do this instead DLog(@"%@", aStringVariable);
#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__);

更多信息:The Evolution of a Replacement for NSLog

【讨论】:

    猜你喜欢
    • 2012-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    • 2022-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多