发行iPhone版应用程序时,如果禁用NSLog();
它,性能会更好吗?
NSLog()
整个应用程序中有多少。NSLog()
需要花费时间才能执行,并增加了应用程序运行时的额外开销。无论如何,如果使用简单的DEBUG预处理程序宏有助于提高性能,则应禁用它。
发行iPhone版应用程序时,如果禁用NSLog();
它,性能会更好吗?
NSLog()
整个应用程序中有多少。NSLog()
需要花费时间才能执行,并增加了应用程序运行时的额外开销。无论如何,如果使用简单的DEBUG预处理程序宏有助于提高性能,则应禁用它。
Answers:
一种方法是进入Build设置,然后在Debug配置下将一个值添加到“ Preprocessor Macros”值中,例如:
DEBUG_MODE=1
确保仅对调试配置执行此操作,而不对Beta版或发行版执行此操作。然后,在公共头文件中,您可以执行以下操作:
#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
。在测试和调试时,您会收到调试消息。当您准备发布Beta或最终版本时,所有这些DLog
行都会自动变空并且不发出任何内容。这样就无需手动设置变量或注释NSLogs
必需项。选择构建目标即可解决这一问题。
Xcode 5和iOS 7更新
注意:对于要在发行版中删除print()语句的Xcode 7 / Swift 2.1解决方案,请在此处找到我的答案。
是的,您应该在发布代码中删除任何NSLog语句,因为这只会降低代码的速度,并且在发布版本中没有任何用处。幸运的是,在Xcode 5(iOS 7)中,在发行版本中“自动”删除所有NSLog语句非常简单。那么为什么不这样做。
首先执行3个步骤,然后进行一些解释
1)在您的Xcode项目中,找到“ yourProjectName-prefix.pch”文件(通常会在main.m文件所在的“支持文件”组下找到此文件
2)将这3行添加到'.pch'文件的末尾:
#ifndef DEBUG
#define NSLog(...);
#endif
3)测试您的“调试”版本与“发布”版本之间的差异。一种方法是通过“编辑方案”->“运行应用程序名称”->“信息”标签下的“使用调试和发布之间的下拉框”进行选择。在发行版中,您将在调试控制台中看不到任何NSLog输出!
这一切如何运作?
首先,必须知道预处理器相对“笨拙”,并且在调用编译器之前仅充当“文本替换器”。它用#define
语句后的内容替换您“ #define”的所有内容。
#define NSLog(...);
该(...)
代表的括号“什么”()。;
最后也要注意。由于编译器会对其进行优化,因此这并非绝对必要,但我喜欢将其放在此处,因为它更“正确”。在我们之后#define
没有“什么”,因此预处理器将其替换为“什么”,因此它将丢弃整个行,从NSLog...
直到并包括;
。
可以使用#ifdef
(如果定义)或#ifndef
(如果未定义)将define语句设为条件语句
在这里,我们写#ifndef DEBUG
,意思是“如果未定义符号DEBUG”。在#ifdef
或#ifndef
将需要“封闭”与#endif
当构建模式为“ DEBUG”时,Xcode 5默认为我们定义“ DEBUG”符号。在“发行版”中未定义。您可以在项目设置下的“构建设置”选项卡中进行验证->向下滚动至“ Apple LLVM 5.0-预处理”部分->预处理器宏。您会看到未为发行版定义符号'DEBUG'!
最后,.pch文件由Xcode自动创建,并在编译期间自动包含在每个源文件中。因此,好像您将整个#define
内容放入每个源文件中一样。
NSLog
语句,无论内部内容如何。
NSLog
用作“不做任何事情”的声明,例如,将“ if(AllCool) NSLog(@"Cool!Do Nothing!"); else...
pop” NSLog
放到大括号中if(AllCool) {NSLog(@"Cool!Do Nothing!");} else...
我个人最喜欢使用可变参数宏。
#ifdef NDEBUG
#define NSLog(...) /* suppress NSLog when in release mode */
#endif
除了所有明智地评论说根本不在NSLog()
生产中运行的人之外,我还会补充一点:
所有NSLog()
从商店下载您的应用并通过将设备插入运行Xcode的Mac(通过Organizer窗口)运行该应用的人都可以看到所有这些输出字符串。
根据您记录的信息(尤其是如果您的应用与服务器联系,进行身份验证等),这可能是一个严重的安全问题。
print()
,但很可能是这样。
在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
所有好的答案,但是您可以考虑使用另一个小技巧,主要是在应用程序的开发/测试阶段。
如果您只想打开自己的调试代码,而不是可能指示代码直接控制范围之外的消息的消息,则它对于应用程序发布代码也很有用。
绝招:
您只需在.m文件顶部添加以下行,即可关闭每个.m文件的NSLog:
#define NSLog(...)
(注意:请勿将.h文件放到此文件中,而仅将.m文件放进去!)
这只会使编译器NSLog()
通过扩展预处理器宏来进行评估。该宏不执行任何操作,但去除了参数。
如果您想重新打开它,可以随时使用
#undef NSLog
例如,您可以通过执行类似的操作来防止围绕特定方法组对NSLog的调用
#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
...
}
#undef NSLog
在pch文件中在#endif之前写下
#define NSLog() //