28

Does NSLog() have variants that print without the time and date stamps, and the automatic newline?

Thanks. Now with following code, I can print NSString, cString, or objects:

#import <Foundation/Foundation.h>
#import <stdio.h>

int main (int argc, const char * argv[]) {
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

  NSString *s = @"Hello, World!";
  NSDate *today = [NSDate date];

  NSLog(@"%@", s);
  printf("%s at %s", [s UTF8String], [[today description] UTF8String]);

  [pool drain];
  return 0;
}  
Stephen Hsu
  • 5,127
  • 7
  • 31
  • 39

6 Answers6

26

Use printf() instead of NSLog()

NebulaFox
  • 7,813
  • 9
  • 47
  • 65
17

This code will work

#ifdef DEBUG
    #define NSLog(FORMAT, ...) fprintf(stderr,"%s\n", [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
    #define NSLog(...) {}
#endif
Rodrigo
  • 11,909
  • 23
  • 68
  • 101
  • Very nice. @marshaul, why is stderr bad to use? I don't know where NSLog normally writes to. – Stan James Jul 30 '14 at 17:51
  • It's not "bad", it's just missing the point of having separate STDERR and STDOUT streams. The convention is to use STDOUT for "normal" output and STDERR for "abnormal" output (errors etc.). Since the user may explicitly redirect the streams (such as by redirecting STDERR to /dev/null), it doesn't make sense to pipe everything to STDERR. Console/terminal output is output, and errors are errors. The point of all that is that STDOUT is (should be) the normal/default case. – Marshall Eubanks Aug 07 '14 at 11:10
  • Also I might point out that, when considering the original question, the extra "meta"data output by NSLog is actually perfectly appropriate for error-type messages, whereas "normal" console IO for user interface is where nice, clean output is going to really be preferable. And, as I mentioned, this is precisely the case where STDOUT should be used. – Marshall Eubanks Aug 07 '14 at 11:14
  • Can we have this answer in Swift? – Hemang Sep 12 '17 at 11:39
  • I believe you should not have ";" at the end of the line – Bahri Okuroglu Sep 25 '17 at 18:29
16

It bothered me too, so I wrote a function to replace NSLog() and printf():

void IFPrint (NSString *format, ...) {
    va_list args;
    va_start(args, format);

    fputs([[[[NSString alloc] initWithFormat:format arguments:args] autorelease] UTF8String], stdout);

    va_end(args);
}

Then, you can just use it instead of NSLog() (e.g. IFPrint(@"Current date: %@", [NSDate date])), but it won't print out any timestamps or a newline, and you don't have to mess around with C strings and arrays, and whatnot. It's pretty handy, I'd say.

If you want, check out my full code (I've also written a replacement for fprintf, scanf, and fscanf) here.
(There's also an SO topic about it here).

Community
  • 1
  • 1
Itai Ferber
  • 28,308
  • 5
  • 77
  • 83
6

Define a macro

#if __has_feature(objc_arc)
  #define DLog(format, ...) CFShow((__bridge CFStringRef)[NSString stringWithFormat:format, ## __VA_ARGS__]);
#else
  #define DLog(format, ...) CFShow([NSString stringWithFormat:format, ## __VA_ARGS__]);
#endif

And use this macro in you code like

NSLog(@"Content with time stamp");
DLog(@"Content without time stamp");

Here is the output of console

NSLog->2014-01-28 10:43:17.873 TestApp[452:60b] Content with time stamp
DLog -> Content without time stamp


P.S.

If anyone wants Custom Logs which gives you more info like method name / line number etc. can download the open source MLog.h on GitHub.

Community
  • 1
  • 1
Inder Kumar Rathore
  • 39,458
  • 17
  • 135
  • 184
  • 1
    @Charles Thank you, I was just about to do that. I can't believe that edit was approved. I voted to reject with the comment "The fact that it's a link makes that clear. This edit is blatant self-promotion that doesn't add any value to the answer." – Adi Inbar Jan 27 '14 at 23:51
  • 1
    Calm down guys, iOSDeveloperTips you have a good site and instead of giving any comment or whatever, you should have contacted me and I would have helped you too. But the idea of `DMCA` has changed my mind and now I have improved my answer in terms of ARC. – Inder Kumar Rathore Jan 28 '14 at 05:32
  • This doesn't show UTF8 non-English letters correctly. It instead displays their unicode number (or whatever it's called) like `\u006z`. – Can Poyrazoğlu Aug 08 '15 at 10:53
  • Not sure why it did, but it instantaneously slowed down my application. The loading took forever. Granted I am doing a lot of NS logs at load time. So I removed it. – Curious101 Apr 14 '18 at 17:27
  • @pankaj I never tried it and hence I don’t know whether it slow down the app or not. – Inder Kumar Rathore Apr 15 '18 at 08:00
4

I like the Itai's solution. I just modified the code to use CFShow under ARC environment.

void CFLog(NSString *format, ...)
{
    va_list args;
    va_start(args, format);

    CFShow((__bridge CFStringRef)[[NSString alloc] initWithFormat:format arguments:args]);

    va_end(args);
}
Kaz Yoshikawa
  • 1,577
  • 1
  • 18
  • 26
3

the FIRST thing I do on ANY project is drop in (my condensed version of) this class... which gets rid of ALL the NONSENSE in NSLog… Place this at the top of an .m file - and your console output will be PERFECT.

#import <Foundation/Foundation.h>
#import <stdio.h>
#define MLogString(s,...) \
    [MLog logFile:__FILE__ lineNumber:__LINE__ \
        format:(s),##__VA_ARGS__]
@interface MLog : NSObject { }
+ (void) logFile:  (char*) sourceFile lineNumber: (int) lineNumber format: (NSString*) format, ...;
+ (void) setLogOn: (BOOL)  logOn;
@end
#ifndef NDEBUG
extern void _NSSetLogCStringFunction(void (*)(const char *string, unsigned length, BOOL withSyslogBanner));
static void PrintNSLogMessage(const char *string, unsigned length, BOOL withSyslogBanner){ puts(string); }
static void HackNSLog(void) __attribute__((constructor));
static void HackNSLog(void){ _NSSetLogCStringFunction(PrintNSLogMessage); }
#endif
static BOOL __MLogOn = NO;
@implementation MLog
+ (void) initialize { char * env = getenv("MLogOn");
     if (strcmp(env == NULL ? "" : env, "NO") != 0) __MLogOn = YES;
}
+ (void) logFile: (char *) sourceFile lineNumber: (int) lineNumber format: (NSString *) format, ...; {
    va_list ap;    NSString *print, *file;
    if (__MLogOn == NO) 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); return;
}
+ (void) setLogOn: (BOOL) logOn { __MLogOn = logOn; }
@end
Alex Gray
  • 16,007
  • 9
  • 96
  • 118