Objective c 如何打印出方法名称和行号并有条件地禁用NSLog?

Objective c 如何打印出方法名称和行号并有条件地禁用NSLog?,objective-c,cocoa,cocoa-touch,xcode,nslog,Objective C,Cocoa,Cocoa Touch,Xcode,Nslog,我正在做一个关于在Xcode中调试的演示,希望获得更多关于有效使用NSLog的信息 特别是,我有两个问题: 有没有办法轻松地记录当前方法的名称/行号 在编译发布代码之前,是否有一种方法可以轻松地“禁用”所有NSLog 输出文件名、行号和函数名: /proj/cocoa/cdcli/cdcli.m 121 managedObjectContext managedObjectContext 代码>函数> C++中的函数>代码> >代码>函数>代码>显示良好的函数名,在COCOA中它们看起来相同

我正在做一个关于在Xcode中调试的演示,希望获得更多关于有效使用NSLog的信息

特别是,我有两个问题:

  • 有没有办法轻松地记录当前方法的名称/行号
  • 在编译发布代码之前,是否有一种方法可以轻松地“禁用”所有NSLog
输出文件名、行号和函数名:

/proj/cocoa/cdcli/cdcli.m 121 managedObjectContext managedObjectContext
<>代码>函数> C++中的函数>代码> >代码>函数>代码>显示良好的函数名,在COCOA中它们看起来相同。 我不确定禁用NSLog的正确方法是什么,我做到了:

#define NSLog

并且没有显示日志输出,但是我不知道这是否有任何副作用。

以下是一些关于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宏仅用于在设置调试变量时输出(-DDEBUG位于调试确认的项目C标志中)

ALog将始终输出文本(如常规NSLog)

输出(例如,ALog(@“Hello world”))如下所示:

-[LibraryController awakeFromNib] [Line 364] Hello world
BOOL myDebugEnabled = FALSE;
#define DLog(fmt, ...) if (myDebugEnabled) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
我的答案可能会有帮助,看起来像是迪德里克做的一样。您可能还想用自己的自定义日志类的静态实例来替换对
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
#定义调试模式
#ifdef调试_模式
#定义调试日志,…)NSLog(@“%@”,self,
[[NSString stringWithUTF8String:[uuuuuuu文件\uuuuuuuu]最后路径组件],
__第二行,
[NSString stringWithFormat:(s),
##__VA_ARGS__;])
#否则
#定义调试日志,…)
#恩迪夫

为了补充上述答案,在某些情况下,尤其是在调试时,使用NSLog的替代品可能非常有用。例如,去掉每行上的所有日期和进程名称/id信息可以使输出更可读,启动更快

下面的链接提供了很多有用的信息,可以让简单的日志记录变得更好


这里是我们使用的调试常量的一个大集合。享受

// 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

禁用所有NSLog,对于对宏过敏的人,您也可以编译以下内容:

void SJLog(NSString *format,...)
{
    if(LOG)
    {   
        va_list args;
        va_start(args,format);
        NSLogv(format, args);
        va_end(args);
    }
}
而且,使用它就像使用NSLog一样:

SJLog(@"bye bye NSLogs !");

从这个博客:

我从上面获取了
DLog
ALog
,并添加了
ULog
,这会引发
UIAlertView
消息

总结如下:

  • DLog
    仅在设置调试变量时才会像
    NSLog
    一样输出
  • ALog
    将始终像
    NSLog
  • ULog
    仅在设置调试变量时才会显示
    UIAlertView

#ifdef调试 #定义DLog(fmt,…)NSLog((@“%s[行%d]”fmt)、\uuu漂亮的函数\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu; #否则 #定义DLog(…) #恩迪夫 #定义ALog(fmt,…)NSLog((@“%s[行%d]”fmt)、\uuuu漂亮的函数\uuuuuuuu、\uuuuuu行\uuuuuuuu、\u35; uu瓦参数); #ifdef调试 #定义ULog(fmt,…){UIAlertView*alert=[[UIAlertView alloc]initWithTitle:[NSString stringWithFormat:@“%s\n[第%d行],uu PRETTY_函数,uuuuuuu Line_uuuu]消息:[NSString stringWithFormat:fmt,##uu VA_uuArgs]委托:nil cancelButtonTitle:@“Ok”其他按钮:nil];[alert show]} #否则 #定义ULog(…) #恩迪夫 这就是它看起来的样子:


+1迪德里克

DLog的新添加。不要从发布的应用程序中完全删除调试,只禁用它。当用户遇到需要调试的问题时,只需告诉用户如何在发布的应用程序中启用调试,并通过电子邮件请求日志数据

简短版本:创建全局变量(是的,懒惰且简单的解决方案)并修改DLog,如下所示:

-[LibraryController awakeFromNib] [Line 364] Hello world
BOOL myDebugEnabled = FALSE;
#define DLog(fmt, ...) if (myDebugEnabled) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);

在乔姆尼乌斯·伊莱松,我学到了更多的答案:

有一个没有答案的新把戏。您可以使用
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

在以上答案的基础上,以下是我剽窃并得出的结论。还添加了内存日志记录

#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
#导入
#ifdef调试
#定义调试日志(fmt,…)NSLog(@“%s(%d)”fmt)、\uuuu漂亮的函数\uuuuuuuuuu、\uuuuuuuuuuuuuu线\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
#否则
#定义调试日志(…)
#恩迪夫
#定义AlwaysLog(fmt,…)NSLog((@“%s(%d)”fmt)、\uuu漂亮的函数\uuuuuuuu、\uuuuuuuuuu线条\uuuuuuuu、\u35; uuuu瓦参数);
#ifdef调试
#定义警报日志(fmt,…{\
UIAlertView*警报=[[UIAlertView alloc]\
initWithTitle:[NSString stringWithFormat:@“%s(行:%d)”,\uuuu漂亮的函数\uuuuuuu,\uuuuu行\uuuuu]\
消息:[NSString stringWithFormat:fmt,###(u#u VA_ARGS)]\
代表:无\
取消按钮:@“确定”\
其他按钮:无]\
[警报显示]\
}
#否则
#定义AlertLog(…)
#恩迪夫
#ifdef调试
#定义DPFLog NSLog(@“%s(%d)”,\uuuuu PRETTY\u FUNCTION\uuuuu,\uuuuu LINE\uuuu)//调试函数日志
#否则
#定义DPFLog
#恩迪夫
#ifdef调试
#定义MemoryLog{\
结构任务\基本\信息\
马赫数、型号、尺寸=尺寸(信息)\
kern\u return\u t e=任务信息(mach\u task\u self()\
任务\基本\信息\
(任务信息)和信息\
&尺寸)\
if(KERN_SUCCESS==e){\
NSNumberFormatter*格式化程序=[[NSNumberFormatter alloc]init]\
[格式化程序setNumberStyle:NSNumberFormatterDecimalStyle]\
调试日志(@“%@字节”,[formatter stringFromNumber:[NSNumber numberWithInteger:info.resident_size]]\
}否则{\
调试日志(@“任务信息错误():%s”,马赫错误字符串(e))\
}\
}
#否则
#定义MemoryLog
#恩迪夫

很容易更改现有的
#define NSLog(__FORMAT__, ...) NSLog((@"%s [Line %d] " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#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
#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
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.
    NSLog(@"%s", __PRETTY_FUNCTION__);