在发布应用程序之前是否需要禁用NSLog?
当释放iPhone的应用程序,如果我禁用NSLog();
它会performance更好吗?
一种方法是进入“生成”设置,在“debugging”configuration下向“预处理器macros”值添加一个值,如下所示:
DEBUG_MODE=1
确保您只对Debugconfiguration执行此操作,而对于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
。 在testing和debugging时,你会得到debugging消息。 当您准备发布testing版或最终版时,所有这些DLog
自动变为空,并且不会发出任何消息。 这样就不需要手动设置variables或者注释NSLogs
。 select你的build立目标照顾它。
更新Xcode 5和iOS 7
注意:对于Xcode 7 / Swift 2.1解决scheme来删除发布版本中的print()语句,请在这里find我的答案。
是的,你应该删除你的发布代码中的任何NSLog语句,因为它只会减慢你的代码,并且在发行版中没有任何用处。 幸运的是,在Xcode 5(iOS 7)中,在发布版本中“自动”删除所有的NSLog语句是非常简单的。 那么为什么不这样做。
首先要采取的三个步骤,然后一些解释
1)在你的Xcode项目中,find'yourProjectName-prefix.pch'文件(通常你会在你的main.m文件所在的组的“支持文件”
2)在'.pch'文件的末尾添加这3行:
#ifndef DEBUG #define NSLog(...); #endif
3)testing你的“debugging”和“发布”版本之间的差异。 一种方法是使用debugging和发布之间的下拉框,通过“编辑scheme” – >“运行应用程序名称” – >在“信息”选项卡下select。 在发行版本中,您将不会在debugging控制台中看到任何NSLog输出!
这一切是如何工作的?
首先,必须知道预处理器是相对“愚蠢”的,在调用编译器之前,它只是作为“文本replace器”。 它取代了#define
语句后面的任何内容。
#define NSLog(...);
(...)
代表括号()之间的“任何”。 也介意;
最后。 这不是严格必要的,因为编译器会优化这一点,但我喜欢把它放在那里,因为它更加“正确”。 在我们的#define
之后没有任何东西,所以预处理器会用'Nothing'replace它,所以它只会丢掉整个行,从NSLog...
开始NSLog...
直到包括;
。
定义语句可以使用#ifdef
(如果已定义)或#ifndef
(如果未定义)
这里我们写了#ifndef DEBUG
,意思是“如果符号DEBUG没有定义”。 #ifdef
或#ifndef
需要用#endif
“closures”
当编译模式为DEBUG时,Xcode 5默认为我们定义了“DEBUG”符号。 在“发布”中没有定义。 你可以在你的项目设置下进行validation,选项卡'Build settings' – >向下滚动到'Apple LLVM 5.0 – Preprocessing' – >预处理器macros。 你会发现符号'DEBUG'没有定义发布版本!
最后,.pch文件由Xcode自动创build,并在编译期间自动包含在每个源文件中。 所以就好像你将整个#define
事物放到每个源文件中一样。
几乎所有以上的答案都是一个解决scheme,但不能解释问题。 我在谷歌search,并find原因。 这是我的答案:
是的,如果你在发行版中注释掉NSLog,性能会变好。 因为NSLog很慢。 为什么? NSLog将做两件事情1)写日志消息到苹果系统日志(ASL),2)如果应用程序运行在Xcode它也写入标准错误。
主要问题在于第一个问题。 为了实现线程安全, 每次调用NSLog时,都会打开与ASL设施的连接 ,发送消息并closures连接。 连接操作非常昂贵。 另一个原因是NSLog花了一些时间来获取日志的时间戳。
从这里引用。
我个人最喜欢的是使用可变macros。
#ifdef NDEBUG #define NSLog(...) /* suppress NSLog when in release mode */ #endif
除了所有明智地评论说在生产环境中根本不调用NSLog的人都会稍微快一点,我会补充一点:
所有这些NSLog输出string对于从商店下载应用程序并将其插入到运行Xcode的mac (通过Organizer窗口)中运行的人都是可见的 。
根据您logging的信息(尤其是如果您的应用程序联系服务器,进行身份validation等), 这可能是一个严重的安全问题 。
在Xcode中项目的当前默认设置里面, NS_BLOCK_ASSERTIONS
macros在发布版本中被设置为1,在Debug版本中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
是的,你应该禁用它。 特别是如果你想尽量提高代码的速度。 NSLogLog事情左右污染的系统日志,其他开发人员可能试图挖掘,它可以对速度至关重要的代码(内部循环,等等)有很大的影响。我不小心留在recursion函数一些日志消息和“以30%的速度增加!”发布了更新 几个星期后… 😉
所有好的答案,但是这里是另一个小技巧,你可以考虑使用,主要是在你的应用程序的开发/testing阶段。
如果您只想打开您的debugging代码,而不是可能指示您的代码直接控制之外的问题的消息,它也可能对应用程序发布代码有用。
诀窍:
您可以通过简单地在.m文件的顶部包含跟随行来closuresNSLog .m文件 :
#define NSLog(...)
( 注意: 不要把这个.h文件,只有.m文件! )
这只是让编译器通过扩展预处理器macros来改变NSLog()
的值。 macros没有做任何事情,只是删除了参数。
如果你想再次打开它,你可以随时使用
#undef NSLog
你可以例如只是通过做一些类似的事情来防止围绕特定的一组方法调用NSLog
#define NSLog(...) -(void) myProblematicMethodThatSometimesNeedsDebugging { ... } #undef NSLog
NSLog很慢,不应该用于发布版本。 像下面这样一个简单的macros将会禁用它,以及任何你也应该禁用的断言。 在不太常见的情况下,您希望NSLog在发布版本中,只需直接调用它即可。 别忘了将“-DNDEBUG”添加到“其他c标志”版本设置中。
#ifdef NDEBUG #define MYLog(f, ...) #else #define MYLog(f, ...) NSLog(f, ## __VA_ARGS__) #endif
在pch文件中写下#endif之前
#define NSLog() //
那这个呢?
#ifndef DEBUG_MODE fclose(stderr); // the simplest way to disable output from NSLog #endif
var showDebugLogs = false; func DLog(format: String, args: CVarArgType...) { if showDebugLogs{ println(String(format: format, arguments: args)) } }
这也将接受额外的参数..只要showDebugLogs参数值为true或false,根据您的需要