[ACCEPTED]-How to print out the method name and line number and conditionally disable NSLog?-nslog
Here are some useful macros around NSLog 7 I use a lot:
#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__)
The DLog macro is used to only 6 output when the DEBUG variable is set (-DDEBUG 5 in the projects's C flags for the debug 4 confirguration).
ALog will always output 3 text (like the regular NSLog).
The output 2 (e.g. ALog(@"Hello world") ) will look like 1 this:
-[LibraryController awakeFromNib] [Line 364] Hello world
I've taken DLog
and ALog
from above, and added ULog
which 2 raises a UIAlertView
message.
To summarize:
DLog
will output likeNSLog
only when the DEBUG variable is setALog
will always output likeNSLog
ULog
will show theUIAlertView
only when the DEBUG variable is set
#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
This is what 1 it looks like:
+1 Diederik
NSLog(@"%s %d %s %s", __FILE__, __LINE__, __PRETTY_FUNCTION__, __FUNCTION__);
Outputs file name, line number, and function 6 name:
/proj/cocoa/cdcli/cdcli.m 121 managedObjectContext managedObjectContext
__FUNCTION__
in C++ shows mangled name __PRETTY_FUNCTION__
shows nice 5 function name, in cocoa they look the same.
I'm 4 not sure what is the proper way of disabling 3 NSLog, I did:
#define NSLog
And no logging output showed 2 up, however I don't know if this has any 1 side effects.
Here one big collection of debug constants 1 that we use. Enjoy.
// 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
There are a new trick that no answer give. You 3 can use printf
instead NSLog
. This will give you a 2 clean log:
With NSLog
you get things like this:
2011-11-03 13:43:55.632 myApp[3739:207] Hello Word
But 1 with printf
you get only:
Hello World
Use this code
#ifdef DEBUG
#define NSLog(FORMAT, ...) fprintf(stderr,"%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
#define NSLog(...) {}
#endif
My answer to this question might help, looks like it's 8 similar to the one Diederik cooked up. You 7 may also want to replace the call to NSLog()
with 6 a static instance of your own custom logging 5 class, that way you can add a priority flag 4 for debug/warning/error messages, send messages 3 to a file or database as well as the console, or 2 pretty much whatever else you can think 1 of.
#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
Disabling all NSLogs, for somebody allergic 3 to MACROS, here is something that you can 2 compile too:
void SJLog(NSString *format,...)
{
if(LOG)
{
va_list args;
va_start(args,format);
NSLogv(format, args);
va_end(args);
}
}
And, use it almost like NSLog:
SJLog(@"bye bye NSLogs !");
From 1 this blog: https://whackylabs.com/logging/ios/2011/01/19/ios-moving-in-and-out-of-nslogs/
To complement the answers above, it can 8 be quite useful to use a replacement for 7 NSLog in certain situations, especially 6 when debugging. For example, getting rid 5 of all the date and process name/id information 4 on each line can make output more readable 3 and faster to boot.
The following link provides 2 quite a bit of useful ammo for making simple 1 logging much nicer.
It's easy to change your existing NSLogs 3 to display line number and class from which 2 they are called. Add one line of code to 1 your prefix file:
#define NSLog(__FORMAT__, ...) NSLog((@"%s [Line %d] " __FORMAT__), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
It is simple,for Example
-(void)applicationWillEnterForeground:(UIApplication 1 *)application {
NSLog(@"%s", __PRETTY_FUNCTION__);
}
Output: -[AppDelegate applicationWillEnterForeground:]
building on top of above answers, here is 2 what I plagiarized and came up with. Also 1 added memory logging.
#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
New addition to DLog. Instead of totally 7 removing debug from released application, only 6 disable it. When user has problems, which 5 would require debugging, just tell how to 4 enable debug in released application and request log data via email.
Short version: create 3 global variable (yes, lazy and simple solution) and 2 modify DLog like this:
BOOL myDebugEnabled = FALSE;
#define DLog(fmt, ...) if (myDebugEnabled) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
Longer answer at Jomnius 1 iLessons iLearned: How to Do Dynamic Debug Logging in Released Application
For some time I've been using a site of 21 macros adopted from several above. Mine 20 focus on logging in the Console, with the 19 emphasis on controlled & filtered verbosity; if you don't mind a lot of 18 log lines but want to easily switch batches 17 of them on & off, then you might find 16 this useful.
First, I optionally replace 15 NSLog with printf as described by @Rodrigo 14 above
#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
Next, I switch logging on or off.
#ifdef DEBUG
#define LOG_CATEGORY_DETAIL// comment out to turn all conditional logging off while keeping other DEBUG features
#endif
In 13 the main block, define various categories corresponding 12 to modules in your app. Also define a logging 11 level above which logging calls won't be called. Then 10 define various flavours of NSLog output
#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
Thus, with 9 current settings for kLOGIFcategory and 8 kLOGIFdetailLTEQ, a call like
myLogLine(kLogVC, 2, @"%@",self);
will print 7 but this won't
myLogLine(kLogGCD, 2, @"%@",self);//GCD not being printed
nor will
myLogLine(kLogGCD, 12, @"%@",self);//level too high
If you want to override 6 the settings for an individual log call, use 5 a negative level:
myLogLine(kLogGCD, -2, @"%@",self);//now printed even tho' GCD category not active.
I find the few extra characters 4 of typing each line are worth as I can then
- Switch an entire category of comment on or off (e.g. only report those calls marked Model)
- report on fine detail with higher level numbers or just the most important calls marked with lower numbers
I'm 3 sure many will find this a bit of an overkill, but 2 just in case someone finds it suits their 1 purposes..
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.