120

为 iPhone 发布应用程序时,如果我禁用NSLog();它会更好吗?

4

12 回答 12

128

一种方法是进入您的构建设置并在调试配置下为“预处理器宏”值添加一个值,例如:

DEBUG_MODE=1

确保您仅针对 Debug 配置执行此操作,而不针对 Beta 或 Release 版本执行此操作。然后在一个通用的头文件中,您可以执行以下操作:

#ifdef DEBUG_MODE
#define DLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DLog( s, ... ) 
#endif

现在而不是到处NSLog 使用。DLog在测试和调试时,您会收到调试消息。当您准备发布测试版或最终版时,所有这些DLog行都会自动变为空,并且不会发出任何内容。这样就不需要手动设置变量或注释NSLogs所需的内容。选择你的构建目标会处理它。

于 2010-01-08T05:40:40.793 回答
119

Xcode 5 和 iOS 7 的更新

注意:对于在发布版本中删除print()语句的Xcode 7 / Swift 2.1解决方案,请在此处找到我的答案。

是的,您应该删除发布代码中的任何 NSLog 语句,因为它只会减慢您的代码速度,并且在发布版本中没有任何用处。幸运的是,在 Xcode 5 (iOS 7) 中,在发布版本中“自动”删除所有 NSLog 语句非常简单。那么为什么不这样做呢。

首先是要采取的 3 个步骤,然后是一些解释

1)在你的Xcode项目中,找到'yourProjectName-prefix.pch'文件(通常你会在'supporting files'组下找到它,你的main.m文件所在的位置

2) 在“.pch”文件的末尾添加这 3 行:

#ifndef DEBUG
   #define NSLog(...);
#endif

3)测试您的“调试”和“发布”版本之间的差异。一种方法是通过“编辑方案”->“运行应用程序名称”-> 在“信息”选项卡下使用调试和发布之间的下拉框进行选择。在发布版本中,您不会在调试控制台中看到任何 NSLog 输出!

这一切如何运作?

首先,必须知道预处理器相对“笨”,在调用编译器之前只是充当“文本替换器”。#define它用语句后面的内容替换您“#define”的任何内容。

#define NSLog(...);

(...)代表括号()之间的“任何东西” 。心也;于末。这不是绝对必要的,因为编译器会优化它,但我喜欢把它放在那里,因为它更“正确”。在我们的#definethere is 'nothing' 之后,预处理器会将其替换为 'nothing',因此它只会丢弃完整的行,从NSLog...until 开始并包括;.

可以使用#ifdef(如果已定义)或#ifndef(如果未定义)使定义语句有条件

这里我们写#ifndef DEBUG,这意味着'如果符号 DEBUG 没有定义'。#ifdef#ifndef需要“关闭”#endif

当 de build mode 为“DEBUG”时,Xcode 5 默认为我们定义了“DEBUG”符号。在“发布”中,这是没有定义的。您可以在项目设置下验证这一点,选项卡“构建设置”-> 向下滚动到“Apple LLVM 5.0 - 预处理”-> 预处理器宏部分。您会看到符号“DEBUG”没有为发布版本定义!

最后,.pch 文件由 Xcode 自动创建,并在编译期间自动包含在每个源文件中。因此,就好像您将整个#define内容放入每个源文件中一样。

于 2014-01-26T16:57:20.447 回答
34

几乎所有上述答案都提出了解决方案,但没有解释问题。我在google上搜索了一下,找到了原因。这是我的答案:

是的,如果您在发布版本中注释掉 NSLog,性能会变得更好。因为 NSLog 很慢。为什么?NSLog 将做两件事 1) 将日志消息写入 Apple System Logging(ASL),2) 如果应用程序在 xcode 中运行,它也会写入 stderr。

主要问题在于第一个问题。为了实现线程安全,每次调用 NSLog 时,它都会打开与 ASL 设施的连接,发送消息,然后关闭连接。连接操作非常昂贵。另一个原因是 NSLog 花费一些时间来获取要记录的时间戳。

这里参考。

于 2013-07-19T05:27:15.287 回答
23

我个人最喜欢的是使用可变参数宏。

#ifdef NDEBUG
    #define NSLog(...) /* suppress NSLog when in release mode */
#endif
于 2013-01-11T00:17:28.563 回答
21

除了所有明智地评论说NSLog()在生产中根本不调用运行速度稍快的人之外,我还要补充一点:

所有这些NSLog()输出字符串对于从商店下载您的应用程序并使用插入到运行 Xcode 的 mac 的设备(通过 Organizer 窗口)运行它的任何人都是可见的。

根据您记录的信息(尤其是如果您的应用程序联系服务器、进行身份验证等),这可能是一个严重的安全问题

于 2013-12-03T05:55:48.237 回答
14

项目默认设置

在 Xcode 项目的当前默认设置中,NS_BLOCK_ASSERTIONS宏将在发布版本和DEBUG=1调试版本中设置为 1。

所以,我更喜欢下面的方法。

// NS_BLOCK_ASSERTIONS is defined by default, as shown in the screenshot above.
// Or, you can define yourself Flags in the `Other C Flags` -> `Release`.
#ifndef NS_BLOCK_ASSERTIONS
    #define _DEBUG
#endif

#ifdef _DEBUG
// for debug mode 
#define DLog(fmt,...) NSLog(@"%s " fmt, __FUNCTION, ##__VA_ARGS__) 
... /// something extra
#else
// for release mode
#define DLog(fmt,...) /* throw it away */
... /// something extra
#endif
于 2011-12-27T02:45:56.073 回答
5

是的,您应该禁用它。特别是如果您试图最大限度地提高代码的速度。NSLogging 左右的东西会污染其他开发人员可能试图挖掘的系统日志,并且它可能对速度关键代码(内部循环等)产生很大影响。我不小心在递归函数中留下了一些日志消息一次并且必须发布“速度提升 30%”的更新!几周后... ;-)

于 2010-01-08T04:36:25.207 回答
5

所有好的答案,但是您可以考虑使用另一个小技巧,主要是在应用程序的开发/测试阶段。

如果您只想关闭您的调试代码,而不是可能表明您的代码直接控制之外的问题的消息,它也可能对应用程序发布代码有用。

诀窍:

您可以通过简单地在 .m 文件顶部包含以下行来关闭每个 .m 文件的 NSLog

#define NSLog(...)

注意:不要把它放在 .h 文件中,只放在 .m 文件中!

这只是使编译器NSLog()通过扩展您的预处理器宏来进行评估。宏除了去掉参数什么都不做。

如果您想再次打开它,您可以随时使用

#undef NSLog

例如,您可以通过执行类似的操作来防止围绕特定方法组调用 NSLog

#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
    ...
}
#undef NSLog
于 2013-10-09T00:35:27.820 回答
3

NSLog is slow and should not be used for release builds. A simple macro like the one below will disable it along with any asserts you might have which should also be disabled. In the less common case where you do want NSLog in a release build, just call it directly. Don't forget to add "-DNDEBUG" to your "other c flags" build settings.

#ifdef NDEBUG
#define MYLog(f, ...) 
#else
#define MYLog(f, ...) NSLog(f, ## __VA_ARGS__)
#endif
于 2010-01-17T05:53:55.193 回答
2

在 pch 文件中在 #endif 之前写下这个

#define NSLog() //
于 2013-09-25T05:28:18.047 回答
0

那这个呢?

#ifndef DEBUG_MODE
        fclose(stderr);     // the simplest way to disable output from NSLog
#endif    
于 2012-02-15T19:48:00.687 回答
0
var showDebugLogs = false;

    func DLog(format: String, args: CVarArgType...) {
        if showDebugLogs{
        println(String(format: format, arguments: args))
        }
    }

这也将接受其他参数。根据您的需要,只需将 showDebugLogs 参数值设置为 true 或 false

于 2015-06-02T09:42:40.863 回答