iOS: Moving in and out of NSLogs.

  • Sharebar

So, if you are a iPhone developer like me you must be using a lot of NSLog in your code, and at times you must have really wished for a way to turn them all ON and OFF from single place.
Here is a easy way I do it.

Step 1: Create a SJLogger.h and SJLogger.m. In the SJLogger.h add this macro:

/*
 1: ON
 0: OFF
 */
#define LOG 1

Step 2: Put this code in SJLogger.m file:

void SJLog(NSString *format,...)
{
	if(LOG)
	{	
		va_list args;
		va_start(args,format);
		NSLogv(format, args);
		va_end(args);
	}
}

Step 3: Now replace all the NSLogs with SJLog, like:

SJLog(@"Simple log");
NSArray *arr = [NSArray arrayWithObjects:@"This",@"is",@"a",@"array",@"log",nil];
SJLog(@"%@",arr);
NSString *str = @"This is a string log";
SJLog(str);
SJLog(@"This is formatted %@",@"log");

Quick Tip: Use Cmd + Shift + F and replace all occurrence of NSLog with SJLog

Step 4: Now, anytime you wanna turn logs ON/OFF, just set the DEBUG MACRO in SJLogger.h accordingly.

Get the SJLogger.tar from here.
Happy Logging :)

FEW MONTHS LATER…

The original code was great, but as I’d already mentioned that I’m going to upgrade this code to be more meaningful(read comments). One big problem with our code is it doesn’t prints filename or line number, so it is hard at time if you just want to comment the log at one place and not all logs entirely.
Then, today I ran into this awesome article by AgentM, and it made me update my code as:

//SJLogger.h
#define SJLog(s,...) [SJLogger logFile:__FILE__ lineNumber:__LINE__ format:(s),##__VA_ARGS__]

/*
 1: ON
 0: OFF
 */
#define LOG 1

@interface SJLogger : NSObject {

}

+(void)logFile:(char*)sourceFile lineNumber:(int)lineNumber format:(NSString*)format, ...;
@end
@implementation SJLogger
+(void)logFile:(char*)sourceFile lineNumber:(int)lineNumber format:(NSString*)format, ...
{
    va_list ap;
	NSString *print,*file;
	if(!LOG)
		return;
	va_start(ap,format);
	file=[[NSString alloc] initWithBytes:sourceFile length:strlen(sourceFile) encoding:NSUTF8StringEncoding];
	print=[[NSString alloc] initWithFormat:format arguments:ap];
	va_end(ap);
    //NSLog handles synchronization issues
	NSLog(@"%s:%d %@",[[file lastPathComponent] UTF8String],lineNumber,print);
	[print release];
	[file release];
}
@end

What I like in this approach is the fact that it carefully uses NSLog at the core, so we should get all the current and future benefits of NSLog (though I highly doubt the future part).

I haven’t used this in my production code, but I’m planning to update the files, fingers crossed :)

This entry was posted in dev, iOS and tagged , , . Bookmark the permalink.
  • Laurent Tarral

    Thanks! And do you #import the SJLogger.h (I get some warnings but it works) or the SJLogger.m (I get an error) in the classes which use SJLog?

    • http://whackylabs.com sid

      I import SJLogger.h, yes there’s a warning and I’m planning on to upgrade the code to add conditional level flags like:DEADLY, WARNING, INFO,.. something like the Java’s Logger class. 
      But for now its serving the purpose :)

  • Laurent Tarral

    Thanks! And do you #import the SJLogger.h (I get some warnings but it works) or the SJLogger.m (I get an error) in the classes which use SJLog?

    • http://whackylabs.com chunkyguy

      I import SJLogger.h, yes there’s a warning and I’m planning on to upgrade the code to add conditional level flags like:DEADLY, WARNING, INFO,.. something like the Java’s Logger class. 
      But for now its serving the purpose :)