Answers:
这是我经常使用的有关NSLog的一些有用的宏:
#ifdef DEBUG
# define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
# define DLog(...)
#endif
// ALog always displays output regardless of the DEBUG setting
#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
DLog宏仅在设置DEBUG变量(调试配置的项目C标志中为-DDEBUG)时才用于输出。
ALog将始终输出文本(如常规的NSLog)。
输出(例如ALog(@“ Hello world”))将如下所示:
-[LibraryController awakeFromNib] [Line 364] Hello world
(@"%s [Line %d] " fmt)
导致fmt
将追加到控制字符串?除了此调试宏之外,我没有看到此语法。
我已经采取DLog
和ALog
从上面,并添加ULog
这引起了一UIAlertView
消息。
总结一下:
DLog
将NSLog
仅在设置DEBUG变量时输出ALog
总是输出像 NSLog
ULog
UIAlertView
仅在设置DEBUG变量时
显示#ifdef调试 #定义DLog(fmt,...)NSLog((@“%s [Line%d]” fmt),__PRETTY_FUNCTION__,__LINE__,## __ VA_ARGS__); #其他 #定义DLog(...) #万一 #define ALog(fmt,...)NSLog((@“%s [Line%d]” fmt),__PRETTY_FUNCTION__,__LINE__,## __ VA_ARGS__); #ifdef调试 #define ULog(fmt,...){UIAlertView * alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@“%s \ n [Line%d]”,__PRETTY_FUNCTION__,__LINE__]消息:[NSString stringWithFormat:fmt ,## __ VA_ARGS__]代表:无cancelButtonTitle:@“确定” otherButtonTitles:无];[警报显示];} #其他 #定义ULog(...) #万一
看起来是这样的:
+1 Diederik
DLog
语句后加分号。这很有用,因为如果您在发行版本中DLog
进行了编译,则该程序将被编译为空,并且代码中将留下悬挂的分号。这不是错误,但是如果它跟在另一个分号之后,则可能会发出警告,具体取决于您的设置。
NSLog(@"%s %d %s %s", __FILE__, __LINE__, __PRETTY_FUNCTION__, __FUNCTION__);
输出文件名,行号和函数名:
/proj/cocoa/cdcli/cdcli.m 121 managedObjectContext managedObjectContext
__FUNCTION__
在C ++中,显示混乱的名称__PRETTY_FUNCTION__
显示了不错的函数名称,在可可中,它们看起来相同。
我不确定禁用NSLog的正确方法是什么,我做到了:
#define NSLog
而且没有日志记录输出出现,但是我不知道这是否有任何副作用。
这是我们使用的一大堆调试常量。请享用。
// Uncomment the defitions to show additional info.
// #define DEBUG
// #define DEBUGWHERE_SHOWFULLINFO
// #define DEBUG_SHOWLINES
// #define DEBUG_SHOWFULLPATH
// #define DEBUG_SHOWSEPARATORS
// #define DEBUG_SHOWFULLINFO
// Definition of DEBUG functions. Only work if DEBUG is defined.
#ifdef DEBUG
#define debug_separator() NSLog( @"────────────────────────────────────────────────────────────────────────────" );
#ifdef DEBUG_SHOWSEPARATORS
#define debug_showSeparators() debug_separator();
#else
#define debug_showSeparators()
#endif
/// /// /// ////// /////
#ifdef DEBUG_SHOWFULLPATH
#define debug_whereFull() debug_showSeparators(); NSLog(@"Line:%d : %s : %s", __LINE__,__FILE__,__FUNCTION__); debug_showSeparators();
#else
#define debug_whereFull() debug_showSeparators(); NSLog(@"Line:%d : %s : %s", __LINE__,[ [ [ [NSString alloc] initWithBytes:__FILE__ length:strlen(__FILE__) encoding:NSUTF8StringEncoding] lastPathComponent] UTF8String ] ,__FUNCTION__); debug_showSeparators();
#endif
/// /// /// ////// /////
#define debugExt(args,...) debug_separator(); debug_whereFull(); NSLog( args, ##__VA_ARGS__); debug_separator();
/// /// /// ////// ///// Debug Print Macros
#ifdef DEBUG_SHOWFULLINFO
#define debug(args,...) debugExt(args, ##__VA_ARGS__);
#else
#ifdef DEBUG_SHOWLINES
#define debug(args,...) debug_showSeparators(); NSLog([ NSString stringWithFormat:@"Line:%d : %@", __LINE__, args ], ##__VA_ARGS__); debug_showSeparators();
#else
#define debug(args,...) debug_showSeparators(); NSLog(args, ##__VA_ARGS__); debug_showSeparators();
#endif
#endif
/// /// /// ////// ///// Debug Specific Types
#define debug_object( arg ) debug( @"Object: %@", arg );
#define debug_int( arg ) debug( @"integer: %i", arg );
#define debug_float( arg ) debug( @"float: %f", arg );
#define debug_rect( arg ) debug( @"CGRect ( %f, %f, %f, %f)", arg.origin.x, arg.origin.y, arg.size.width, arg.size.height );
#define debug_point( arg ) debug( @"CGPoint ( %f, %f )", arg.x, arg.y );
#define debug_bool( arg ) debug( @"Boolean: %@", ( arg == YES ? @"YES" : @"NO" ) );
/// /// /// ////// ///// Debug Where Macros
#ifdef DEBUGWHERE_SHOWFULLINFO
#define debug_where() debug_whereFull();
#else
#define debug_where() debug(@"%s",__FUNCTION__);
#endif
#define debug_where_separators() debug_separator(); debug_where(); debug_separator();
/// /// /// ////// /////
#else
#define debug(args,...)
#define debug_separator()
#define debug_where()
#define debug_where_separators()
#define debug_whereFull()
#define debugExt(args,...)
#define debug_object( arg )
#define debug_int( arg )
#define debug_rect( arg )
#define debug_bool( arg )
#define debug_point( arg )
#define debug_float( arg )
#endif
有一个没有答案的新技巧。您可以printf
改为使用NSLog
。这将为您提供干净的日志:
随着NSLog
你得到这样的事情:
2011-11-03 13:43:55.632 myApp[3739:207] Hello Word
但是只有printf
你得到:
Hello World
使用此代码
#ifdef DEBUG
#define NSLog(FORMAT, ...) fprintf(stderr,"%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
#define NSLog(...) {}
#endif
我对这个问题的回答可能会有所帮助,看起来类似于Diederik制作的一个。您可能还想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
%s
Apple正在尝试弃用的格式说明符,并避免-Wcstring-format-directive
了2015
对于对MACROS过敏的人,禁用所有NSLogs也是可以编译的:
void SJLog(NSString *format,...)
{
if(LOG)
{
va_list args;
va_start(args,format);
NSLogv(format, args);
va_end(args);
}
}
并且,几乎像NSLog一样使用它:
SJLog(@"bye bye NSLogs !");
从此博客中访问:https : //whackylabs.com/logging/ios/2011/01/19/ios-moving-in-and-out-of-nslogs/
为了补充上述答案,在某些情况下,尤其是在调试时,使用NSLog替代品可能非常有用。例如,消除每一行上的所有日期和进程名称/ id信息可以使输出更具可读性,并且启动速度更快。
以下链接提供了许多有用的弹药,可简化简单的日志记录。
更改现有的NSLog以显示行号和调用它们的类很容易。在您的前缀文件中添加一行代码:
#define NSLog(__FORMAT__, ...) NSLog((@"%s [Line %d] " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
很简单,例如
-(void)applicationWillEnterForeground:(UIApplication *)application {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
输出: -[AppDelegate applicationWillEnterForeground:]
在以上答案的基础上,我I窃并提出了以下内容。还添加了内存日志记录。
#import <mach/mach.h>
#ifdef DEBUG
# define DebugLog(fmt, ...) NSLog((@"%s(%d) " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define DebugLog(...)
#endif
#define AlwaysLog(fmt, ...) NSLog((@"%s(%d) " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#ifdef DEBUG
# define AlertLog(fmt, ...) { \
UIAlertView *alert = [[UIAlertView alloc] \
initWithTitle : [NSString stringWithFormat:@"%s(Line: %d) ", __PRETTY_FUNCTION__, __LINE__]\
message : [NSString stringWithFormat : fmt, ##__VA_ARGS__]\
delegate : nil\
cancelButtonTitle : @"Ok"\
otherButtonTitles : nil];\
[alert show];\
}
#else
# define AlertLog(...)
#endif
#ifdef DEBUG
# define DPFLog NSLog(@"%s(%d)", __PRETTY_FUNCTION__, __LINE__);//Debug Pretty Function Log
#else
# define DPFLog
#endif
#ifdef DEBUG
# define MemoryLog {\
struct task_basic_info info;\
mach_msg_type_number_t size = sizeof(info);\
kern_return_t e = task_info(mach_task_self(),\
TASK_BASIC_INFO,\
(task_info_t)&info,\
&size);\
if(KERN_SUCCESS == e) {\
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; \
[formatter setNumberStyle:NSNumberFormatterDecimalStyle]; \
DebugLog(@"%@ bytes", [formatter stringFromNumber:[NSNumber numberWithInteger:info.resident_size]]);\
} else {\
DebugLog(@"Error with task_info(): %s", mach_error_string(e));\
}\
}
#else
# define MemoryLog
#endif
DLog的新增功能。与其完全从已发布的应用程序中删除调试,请仅将其禁用。当用户遇到问题(需要调试)时,只需告诉如何在已发布的应用程序中启用调试即可并通过电子邮件请求日志数据即可。
简短版本:创建全局变量(是的,懒惰和简单的解决方案)并按如下所示修改DLog:
BOOL myDebugEnabled = FALSE;
#define DLog(fmt, ...) if (myDebugEnabled) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
Jomnius iLessons iLearned的更长回答:如何在发布的应用程序中进行动态调试日志记录
一段时间以来,我一直在使用上面提到的一些宏站点。我的重点是在控制台中登录,重点是受控和过滤的详细程度;如果您不介意很多日志行,但想轻松地打开或关闭它们的批次,那么您可能会发现这很有用。
首先,我可以选择使用上面@Rodrigo所述的printf替换NSLog
#define NSLOG_DROPCHAFF//comment out to get usual date/time ,etc:2011-11-03 13:43:55.632 myApp[3739:207] Hello Word
#ifdef NSLOG_DROPCHAFF
#define NSLog(FORMAT, ...) printf("%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#endif
接下来,我打开或关闭登录。
#ifdef DEBUG
#define LOG_CATEGORY_DETAIL// comment out to turn all conditional logging off while keeping other DEBUG features
#endif
在主块中,定义与您的应用程序中的模块相对应的各种类别。还定义一个日志记录级别, 超过该级别将不会调用日志记录调用。然后定义各种风格的NSLog输出
#ifdef LOG_CATEGORY_DETAIL
//define the categories using bitwise leftshift operators
#define kLogGCD (1<<0)
#define kLogCoreCreate (1<<1)
#define kLogModel (1<<2)
#define kLogVC (1<<3)
#define kLogFile (1<<4)
//etc
//add the categories that should be logged...
#define kLOGIFcategory kLogModel+kLogVC+kLogCoreCreate
//...and the maximum detailLevel to report (use -1 to override the category switch)
#define kLOGIFdetailLTEQ 4
// output looks like this:"-[AppDelegate myMethod] log string..."
# define myLog(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%s " format), __PRETTY_FUNCTION__, ##__VA_ARGS__);}
// output also shows line number:"-[AppDelegate myMethod][l17] log string..."
# define myLogLine(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%s[l%i] " format), __PRETTY_FUNCTION__,__LINE__ ,##__VA_ARGS__);}
// output very simple:" log string..."
# define myLogSimple(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"" format), ##__VA_ARGS__);}
//as myLog but only shows method name: "myMethod: log string..."
// (Doesn't work in C-functions)
# define myLog_cmd(category,detailLevel,format,...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%@: " format), NSStringFromSelector(_cmd), ##__VA_ARGS__);}
//as myLogLine but only shows method name: "myMethod>l17: log string..."
# define myLog_cmdLine(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%@>l%i: " format), NSStringFromSelector(_cmd),__LINE__ , ##__VA_ARGS__);}
//or define your own...
// # define myLogEAGLcontext(category,detailLevel,format, ...) if(detailLevel<0 || ((category&kLOGIFcategory)&&detailLevel<= kLOGIFdetailLTEQ)) {NSLog((@"%s>l%i (ctx:%@)" format), __PRETTY_FUNCTION__,__LINE__ ,[EAGLContext currentContext], ##__VA_ARGS__);}
#else
# define myLog_cmd(...)
# define myLog_cmdLine(...)
# define myLog(...)
# define myLogLine(...)
# define myLogSimple(...)
//# define myLogEAGLcontext(...)
#endif
因此,在使用kLOGIFcategory和kLOGIFdetailLTEQ的当前设置的情况下,
myLogLine(kLogVC, 2, @"%@",self);
将打印,但这不会
myLogLine(kLogGCD, 2, @"%@",self);//GCD not being printed
也不会
myLogLine(kLogGCD, 12, @"%@",self);//level too high
如果要覆盖单个日志呼叫的设置,请使用负级别:
myLogLine(kLogGCD, -2, @"%@",self);//now printed even tho' GCD category not active.
我发现输入每行的几个额外字符是值得的
我敢肯定,很多人会觉得这有点过头了,但是以防万一有人发现它适合自己的目的。