在发布适用于iPhone的应用时,如果我禁用NSLog();
,它会表现得更好吗?
答案 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)
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)
在#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,根据需要