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

RAG*_*poR 116 iphone nslog ios

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

Ram*_*min 125

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

DEBUG_MODE=1
Run Code Online (Sandbox Code Playgroud)

确保仅对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
Run Code Online (Sandbox Code Playgroud)

现在而不是到处NSLog 使用DLog.在测试和调试时,您将获得调试消息.当您准备发布测试版或最终版时,所有这些DLog行都会自动变为空,并且不会发出任何内容.这种方式不需要手动设置变量或注释NSLogs所需.选择构建目标可以解决它.

  • @SergiusGee:如果找不到该函数的声明,则会得到隐式声明警告,在这种情况下,它会认为您正在尝试声明它.确保您的类可以访问声明它的头文件. (2认同)
  • 我会选择#if而不是#ifdef,因为DEBUG_MODE 0仍将通过真正的路径 (2认同)

Ron*_*ers 116

Xcode 5和iOS 7的更新

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

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

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

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

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

#ifndef DEBUG
   #define NSLog(...);
#endif
Run Code Online (Sandbox Code Playgroud)

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

这一切都有用吗?

首先,必须知道预处理器相对"哑",并且在调用编译器之前只是充当"文本替换器".它取代了#define声明后面的'#define' .

#define NSLog(...);
Run Code Online (Sandbox Code Playgroud)

(...)代表的括号"什么"().心灵也在;最后.这并不是绝对必要的,因为编译器会优化它,但我喜欢把它放在那里,因为它更"正确".在我们#define没有'没有'之后,预处理器将用'nothing'替换它,因此它将丢弃整条线,从NSLog...直到并包括;.

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

在这里我们写#ifndef DEBUG,这意味着'如果没有定义符号DEBUG'.的#ifdef#ifndef需要被"关闭"#endif

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

最后,.pch文件由Xcode自动创建,并在编译期间自动包含在每个源文件中.所以就好像你会将整个#define事情放入每个源文件中一样.


And*_*rew 31

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

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

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

这里参考.


Eyt*_*tan 23

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

#ifdef NDEBUG
    #define NSLog(...) /* suppress NSLog when in release mode */
#endif
Run Code Online (Sandbox Code Playgroud)


Nic*_*ari 19

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

所有这些NSLog()输出字符串对于从商店下载应用程序的任何人都可见,并在设备插入运行Xcode的mac(通过管理器窗口)的情况下运行它.

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

  • @Whasssaaahhh打印不会在设备控制台输出..我刚刚测试过 (3认同)

Aec*_*Liu 13

项目默认设置

在Xcode的项目内部当前默认设置中,NS_BLOCK_ASSERTIONS宏将在发布版本中设置为1,DEBUG=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
Run Code Online (Sandbox Code Playgroud)


Ben*_*tow 5

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


uns*_*zed 5

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

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

诀窍:

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

#define NSLog(...)
Run Code Online (Sandbox Code Playgroud)

(注意:不要把这个.h文件,只有.m文件!)

这只是让编译器NSLog()通过扩展预处理器宏来进行评估.宏除了剥离参数外什么都不做.

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

#undef NSLog
Run Code Online (Sandbox Code Playgroud)

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

#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
    ...
}
#undef NSLog
Run Code Online (Sandbox Code Playgroud)