2013-06-06 16 views
6

Ich versuche, eine benutzerdefinierte NSLog() Methode, DNSLog(), die die NSLog nur ausführt, wenn die Debug-Variable wahr ist.Benutzerdefinierte NSLog-Methode (Variadic)

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

Aber wenn ich es versuchen Aufruf

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

I erhalten einen Kompilierungsfehler:

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) 

ich das als Referenz verwendet haben: http://www.cocoawithlove.com/2009/05/variable-argument-lists-in-cocoa.html

Wo bin ich falsch machen ?

+5

Ich denke du solltest C lernen, bevor du versuchst, in fortgeschrittene Sachen zu kommen. Es scheint, dass Sie nicht einmal zwischen der Syntax einer C-Funktion und einer Objective-C-Methode unterscheiden können ... –

+1

Außerdem ist Ihr Code anfällig für Formatstring-Angriffe/-Fehler. Sie sollten stattdessen 'NSLogv (formatString, args);' verwenden. –

Antwort

14

Sie haben verwirrt Methoden und Funktionen - Objective-C hat beides. NSLog ist eine Standardfunktion, so nennen Sie es als NSLog(...). Sie haben eine Methode definiert:

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

aber versucht, es als eine Funktion zu bezeichnen. So rufen Sie Ihre Methode müssen Sie tun:

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

Als Ihr Code kompiliert Sie ein globales oder Instanz debug Variable haben muss. Wenn es ein global ist, dann könnten Sie DNSLog als eine Funktion definieren (dies wird nicht funktionieren, wenn debug eine Instanzvariable ist, da nur Methoden direkt auf diese zugreifen können). Die Funktion würde starten:

Der Körper der Funktion wird der gleiche wie für die Methode sein.

NSLog hat auch ein Attribut, NS_FORMAT_FUNCTION, um den Compiler zu sagen, dass es eine Formatzeichenfolge als ein Argument, sieht dies der Compiler wird die Formatzeichenfolge und Argumente überprüfen, um zu sehen, dass sie übereinstimmen.Um dies zu tun für Ihre Methode oder Funktion schreiben:

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

oder:

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

in der Schnittstelle oder Header-Datei.

HTH.

+0

Dank ... Ja, erkannte ich, dass mistake.All arbeiten jetzt :) – Kyuubi

+1

@Kyuubi - Ja, Sie einige dieser heraus sich, während ich weg dies in tippte, vergessen Sie nicht das 'NS_FORMAT_FUNCTION' obwohl - es hilft Menge. – CRD

+0

Verstanden. An meine Funktion angefügt. – Kyuubi

12

Anstatt eine benutzerdefinierte Methode zu verwenden, versuchen Sie, dieses Makro zu Ihrer App hinzuzufügen, möglicherweise in Ihrer .pch-Datei.

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

Dies wird ein benutzerdefiniertes Protokoll betreibe ich MyLog aufrufen, wenn im Debug-Modus, und wenn in Freigabe, es wird nicht alles tun. Es gibt auch einige andere nützliche Informationen wie die Datei- und Zeilennummer des Protokolls aus.

+1

Eigentlich war seine Frage nur über Protokollierung, wenn "die Debug-Variable wahr ist". Sein Code scheint anzuzeigen, dass er eine separate Debug-Variable hat, die er steuert. Auch H2CO3 nennt es einfach so, wie er es sieht. Ich fühle das gleiche. Ich stelle Code in Antworten selten selbst zur Verfügung, weil ich weiß, wenn ich Leute kopiere und es nur einfüge und dann ratlos bin, wenn es nicht genau wie geschrieben funktioniert. Ich denke, dass die Leute den Code, den sie schreiben, verstehen sollten. – borrrden

+0

Nun, ist das nicht die Lösung, um eine Antwort zu geben, um ihn zu informieren, damit er es verstehen kann? Vielleicht schaffen wir einen Beitrag, der uns hilft, diese Methode zu lernen und umzusetzen. Und um das hinzuzufügen, sollte es nicht falsch sein, etwas anderes zu tun, aber ich sehe deinen Standpunkt jetzt. – Eric

+0

Danke. Das funktioniert auch! Aber in Zukunft könnte ich einen komplexen booleschen Ausdruck und ein verschachteltes if-else in der Log-Funktion haben, also habe ich versucht, eine neue Funktion zusammen zu implementieren, anstatt eines MACRO. – Kyuubi

9

Vielen Dank für Ihre extrem "wertvolle", "ermutigende" und "unterstützende" Antworten für einen Anfänger.

fand ich meinen Fehler und hier ist der korrigierte Arbeitscode:

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

ZNSLog(@"Hello"); 

Das bisherige Verfahren war ich mit war eine Objective-C Methode

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

, die ich mit einem C zu nennen versuche Funktion Anruf.

Verwandte Themen