在发布应用程序之前是否需要禁用NSLog?

时间:2010-01-08 04:19:28

标签: ios iphone nslog

在发布适用于iPhone的应用时,如果我禁用NSLog();,它会表现得更好吗?

12 个答案:

答案 0 :(得分:125)

一种方法是进入Build设置,在Debug配置下为“Preprocessor Macros”值添加一个值,如:

DEBUG_MODE=1

确保仅对调试配置执行此操作,而不是针对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。选择构建目标需要处理它。

答案 1 :(得分:116)

更新Xcode 5&amp; iOS 7

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

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

首先采取3个步骤,然后进行一些解释

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

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

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

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

这一切如何运作?

首先,必须知道预处理器相对“哑”,并且在调用编译器之前只是充当“文本替换器”。它取代了#define语句后面的“#define”字样。

#define NSLog(...);

(...)代表括号()之间的“任何东西”。最后还要注意;。这并不是绝对必要的,因为编译器会优化它,但我喜欢把它放在那里,因为它更“正确”。在我们的#define之后'没有',所以预处理器将用'nothing'替换它,因此它将丢弃整行,从NSLog...开始直到并包括{{1} }。

可以使用;(如果已定义)或#ifdef(如果未定义)

使条件语句成为条件语句

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

'关闭'

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

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

答案 2 :(得分:31)

几乎所有上述答案都会提出解决方案,但不能解释问题。我在谷歌搜索过,找到了原因。这是我的答案:

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

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

来自here的参考。

答案 3 :(得分:23)

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

#ifdef NDEBUG
    #define NSLog(...) /* suppress NSLog when in release mode */
#endif

答案 4 :(得分:18)

除了明智地评论说在生产中没有完全调用NSLog()的所有人跑得快一点之外,我还要补充一点:

所有这些NSLog()输出字符串对于从商店下载应用并通过设备插入运行Xcode的Mac (通过管理器窗口)运行的所有人都可以看到。

根据您记录的信息(特别是您的应用与服务器联系,进行身份验证等),这可能是一个严重的安全问题

答案 5 :(得分:13)

Project Default Setting

Xcode中项目的当前默认设置,NS_BLOCK_ASSERTIONS宏在发布版本中将设置为1,在调试版本中将设置为DEBUG=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

答案 6 :(得分:5)

是的,你应该禁用它。特别是如果您正在尝试最大化代码的速度。 NSLogging事情左右污染了其他开发人员可能试图挖掘的系统日志,它可能对速度关键代码(内部循环等)产生很大影响。我不小心在一个递归函数中留下了一些日志消息,得到了“速度提高30%!”的更新!几个星期后......; - )

答案 7 :(得分:5)

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

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

诀窍:

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

#define NSLog(...)

注意:执行 NOT 将此.h文件,只有.m文件!

这只是让编译器通过扩展预处理器宏来评估NSLog()。宏没有做任何事情,只是删除了论点。

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

#undef NSLog

例如,您可以通过执行类似

之类的操作来阻止对特定方法组的NSLog调用
#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
    ...
}
#undef NSLog

答案 8 :(得分:3)

NSLog很慢,不应该用于发布版本。如下所示的简单宏将禁用它以及您可能还应禁用的任何断言。在不常见的情况下,您确实需要在发布版本中使用NSLog,只需直接调用它即可。不要忘记将“-DNDEBUG”添加到“其他c标志”构建设置中。

#ifdef NDEBUG
#define MYLog(f, ...) 
#else
#define MYLog(f, ...) NSLog(f, ## __VA_ARGS__)
#endif

答案 9 :(得分:2)

pch文件中的

在#endif

之前写下来
#define NSLog() //

答案 10 :(得分:0)

这是怎么回事?

#ifndef DEBUG_MODE
        fclose(stderr);     // the simplest way to disable output from NSLog
#endif    

答案 11 :(得分:0)

var showDebugLogs = false;

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

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