Kyuubi
Kyuubi

Reputation: 1240

Custom NSLog Method ( Variadic )

I am trying to create a custom NSLog() method , DNSLog() , which executes the NSLog only if the debug variable is true.

-(void)DNSLog:(NSString *)formatString, ...
{
    if(debug){
        va_list args;
        va_start(args, formatString);
        NSLog([[NSString alloc] initWithFormat:formatString arguments:args]);
        va_end(args);
    }
}

But when I try calling it using

DNSLog(@"Hello %d",x);

I receive a compilation error :

Undefined symbols for architecture i386:
  "_DZNSLog", referenced from:
      -[RestaurantInfoViewController viewDidLoad] in RestaurantInfoViewController.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I have used this as a reference : http://www.cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html

Where am I going wrong ?

Upvotes: 6

Views: 7500

Answers (3)

CRD
CRD

Reputation: 53000

You have confused methods and functions - Objective-C has both. NSLog is a standard function so you call it as NSLog(...). You have defined a method:

-(void)DNSLog:(NSString *)formatString, ...

but tried to call it as a function. To call your method you need to do:

[self DNSLog:@"Hello %d", x];

As your code compiles you must have a global or instance debug variable. If it is a global then you could define DNSLog as a function (this won't work if debug is an instance variable as only methods can directly access those). The function would start:

 void DNSLog(NSString *formatString, ...)

The body of the function will be the same as for the method.

NSLog also has an attribute, NS_FORMAT_FUNCTION, on it to tell the compiler that it takes a format string as an argument, seeing this the compiler will check the format string and arguments to see that they match. To do this for your method or function write:

-(void)DNSLog:(NSString *)formatString, ... NS_FORMAT_FUNCTION(1,2);

or:

void DNSLog(NSString *formatString, ...)  NS_FORMAT_FUNCTION(1,2);

in the interface or header file.

HTH.

Upvotes: 15

Kyuubi
Kyuubi

Reputation: 1240

Thank You everyone for your extremely 'valuable', 'encouraging' and 'supporting' answers to a beginner.

I found my mistake and here is the corrected working code :

void ZNSLog(NSString *format, ...){
    if(!ENABLE_DEBUGGING)
        return;
    va_list args;
    va_start(args, format);
    NSLogv(format, args);
    va_end(args);
}

ZNSLog(@"Hello");

The previous method I was using was an Objective C method

-(void)DNSLog:(NSString *)formatString, ...

which I was trying to call using a C function Call.

Upvotes: 11

Eric
Eric

Reputation: 5681

Instead of using a custom method, try adding this macro to your app, perhaps in your .pch file.

#ifdef DEBUG
#define MyLog(x, ...) NSLog(@"%s %d: " x, __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define MyLog(x, ...)
#endif

This will run a custom log I call MyLog when in debug mode, and when in release, it wont do anything. It also prints out some other useful information like the file and line number of the log.

Upvotes: 13

Related Questions