在这个网站上,我已经被告知了几次,但我想确保这是否确实是情况。
我希望能够在我的代码中随处添加NSLog函数调用,并且Xcode / gcc会在构建我的发布/分发版本时自动删除这些调用。
我应该避免使用这个吗?如果是这样,有什么替代方案是经验丰富的Objective-C程序员之间最常见的吗?
在这个网站上,我已经被告知了几次,但我想确保这是否确实是情况。
我希望能够在我的代码中随处添加NSLog函数调用,并且Xcode / gcc会在构建我的发布/分发版本时自动删除这些调用。
我应该避免使用这个吗?如果是这样,有什么替代方案是经验丰富的Objective-C程序员之间最常见的吗?
预处理器宏确实非常适用于调试。NSLog()没有问题,但是定义自己的日志记录函数并具有更好的功能非常简单。这是我使用的一个函数,它包括文件名和行号,以便更容易跟踪日志语句。
#define DEBUG_MODE
#ifdef DEBUG_MODE
#define DebugLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DebugLog( s, ... )
#endif
我发现将整个语句放在前缀头文件中比单独建立一个文件更容易。如果你愿意,可以通过让DebugLog与普通的Objective-C对象相互作用来构建更复杂的日志记录系统。例如,您可以有一个日志记录类,该类写入其自己的日志文件(或数据库),并包括一个“优先级”参数,您可以在运行时设置,以便调试消息不显示在发布版本中,但错误消息是(如果这样做,您可以制作DebugLog(),WarningLog()等)。
哦,记住#define DEBUG_MODE
可以在应用程序的不同位置重复使用。例如,在我的应用程序中,我使用它来禁用许可密钥检查,并仅在它之前运行某个日期时允许应用程序运行。这使我能够轻松地分发时间限制的、完全功能的测试版副本,而无需付出太多的努力。
NSLog()
确实存在真正的风险。滥用NSLog()
可能会导致显著的内存使用量(大量自动释放的字符串)和CPU周期消耗(大量解析、格式化和字节复制)。您绝对不希望在生产环境中承担这样的成本,尤其是在嵌入式设备上! - bbum将这3行放在-prefix.pch文件的末尾:
#ifndef DEBUG
#define NSLog(...) /* suppress NSLog when in release mode */
#endif
当您创建项目时,默认情况下在构建设置中定义了DEBUG
,因此您不需要将任何内容定义到您的项目中。
NSLog调用可以留在生产代码中,但应仅在真正异常的情况下或希望记录到系统日志的信息时才存在。
过多地记录系统日志的应用程序会令人感到烦恼,并显得不专业。
我无法在Marc Charbonneau的回答中进行评论,因此我将这个作为一个答案发布。
除了将宏添加到你的预编译头文件中之外,你还可以使用目标构建配置来控制定义(或不定义)DEBUG_MODE
。
如果选择"Debug"活动配置,DEBUG_MODE
将被定义,宏将扩展为完整的NSLog
定义。
选择"Release"活动配置将不定义DEBUG_MODE
,并且你的NSLog
会在发布版本中省略。
步骤:
GCC_PREPROCESSOR_DEFINITIONS
)DEBUG_MODE=1
GCC_PREPROCESSOR_DEFINITIONS
中未设置DEBUG_MODE
如果在定义中省略'='字符,你将从预处理器中得到一个错误
此外,在宏定义之前插入以下注释以提醒你DEBUG_MACRO
的定义来自何处;)
// Target > Get Info > Build > GCC_PREPROCESSOR_DEFINITIONS
// Configuration = Release: <empty>
// = Debug: DEBUG_MODE=1
DEBUG_MODE
和 DEBUG_MACRO
是不寻常的。我只在苹果网站上找到了一个有关 DEBUG_MACRO
的参考资料(http://www.opensource.apple.com/source/gm4/gm4-15/src/m4.h?txt)。也许更标准的选择是 DEBUG
和 NDEBUG
?NDEBUG
被 POSIX 规定使用,而 DEBUG
则是惯例。 - jww编辑:Marc Charbonneau发布的方法比这个更好,由sho提醒我注意到这一点。
我已删除了我的答案部分,该部分建议使用空函数在调试模式被禁用时禁用日志记录。处理自动预处理器宏的部分仍然相关,因此它仍然存在。我还编辑了预处理器宏的名称,使其更符合Marc Charbonneau的答案。
为实现Xcode中的自动(和期望的)行为:
在项目设置中,转到“Build”选项卡,选择“Debug”配置。找到“Preprocessor Macros”部分,并添加一个名为DEBUG_MODE
的宏。
...
编辑:有关使用DEBUG_MODE
宏启用和禁用日志记录的正确方法,请查看Marc Charbonneau的答案。
我同意Matthew的说法。在生产代码中使用NSLog没有任何问题。实际上,它对用户可能有用。但如果你唯一使用NSLog的原因是为了帮助调试,那么在发布之前应该将其删除。
此外,由于您将此标记为iPhone问题,NSLog会占用资源,而iPhone的资源非常宝贵。如果您在iPhone上记录任何东西,则会从您的应用程序中夺走处理器时间。请明智地使用它。
NSLog
(或其他记录器)正在写入敏感信息,则应在生产代码中删除记录器。NSLog
的使用情况以确保其未记录敏感信息。他/她只会告诉你删除记录器。在您的代码中用 DDLogVerbose 或 DDLogError 等替换 NSLog,添加宏定义等 #import 并设置记录器,通常在 applicationDidFinishLaunching 方法中进行。
要达到与 NSLog 相同的效果,配置代码如下:
[DDLog addLogger:[DDASLLogger sharedInstance]];
[DDLog addLogger:[DDTTYLogger sharedInstance]];
在发布代码中,不应该无谓地使用printf或NSLog。只有当应用程序发生问题(例如,不可恢复的错误)时,请尝试仅使用printf或NSLog。