我正在做一个有关Xcode调试的演示,想获取更多关于高效使用NSLog的信息。
具体来说,我有两个问题:
- 有没有一种简单的方法可以NSLog当前方法的名称/行号?
- 有没有一种简单的方法在编译发布代码之前“禁用”所有NSLog?
我正在做一个有关Xcode调试的演示,想获取更多关于高效使用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宏用于仅在设置了DEBUG变量时输出(-DDEBUG为调试配置的项目C标志)。
ALog将始终输出文本(例如常规NSLog)。
输出结果(例如ALog(@"Hello world"))将如下所示:
-[LibraryController awakeFromNib] [Line 364] Hello world
;
字符,以至于我只是因为这个原因下投了你的评论。让 DLog 看起来像 C/C++/Obj-C 中的每个其他语句,并要求在使用它时添加一个分号,这既更简单,又更有沟通性。这样做使得 DLog() 和 NSLog() 更加可互换(如今,如果你将所有的 DLog
词法地替换为 NSLog
,你将不得不添加回所有那些你避免输入的 ;
,这是不正确的)。 - Cubs Fan Ron#ifdef DEBUG
来声明它。或者忽略警告。 - CœurCalled object of type NSString is not a function or function pointer
。所以我不得不删除括号中的 fmt 表达式:#define ALog(fmt, ...) NSLog(@"%s [Line %d] " fmt, __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
。 - GominoDLog
和ALog
,并添加了ULog
,它会弹出一个UIAlertView
消息。DLog
仅在设置了DEBUG变量时才会像NSLog
一样输出ALog
始终会像NSLog
一样输出ULog
仅在设置了DEBUG变量时才会显示UIAlertView
#ifdef DEBUG # define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); #else # define DLog(...) #endif #define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); #ifdef DEBUG # define ULog(fmt, ...) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:@"%s\n [Line %d] ", __PRETTY_FUNCTION__, __LINE__] message:[NSString stringWithFormat:fmt, ##__VA_ARGS__] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; [alert show]; } #else # define ULog(...) #endif
这是它的外观:
+1 Diederik
DLog
语句后面不需要加分号。这很有用,因为如果你这样做,在发布版本中,DLog
会被编译为空,你的代码中会留下一个悬空的分号。这不是错误,但如果它跟在另一个分号后面,根据你的设置,可能会引发警告。 - Zev EisenbergNSLog(@"%s %d %s %s", __FILE__, __LINE__, __PRETTY_FUNCTION__, __FUNCTION__);
输出文件名、行号和函数名:
/proj/cocoa/cdcli/cdcli.m 121 managedObjectContext managedObjectContext
__FUNCTION__
在C++中显示的是混淆的函数名,__PRETTY_FUNCTION__
显示的是漂亮的函数名,在cocoa中它们看起来相同。
我不确定禁用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
如果有人对宏过敏,想要禁用所有的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 !");
从这篇博客中获取:https://whackylabs.com/logging/ios/2011/01/19/ios-moving-in-and-out-of-nslogs/
将现有的NSLog转换为显示调用它们的行号和类很容易。只需在前缀文件中添加一行代码即可:
#define NSLog(__FORMAT__, ...) NSLog((@"%s [Line %d] " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
以下链接提供了许多有用的资料,可以使简单的日志记录变得更加美观。
-(void)applicationWillEnterForeground:(UIApplication *)application {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
输出结果: -[AppDelegate applicationWillEnterForeground:]