Snabbtips Anpassa NSLog för enklare debugging

I detta snabba tips kommer vi att lära oss hur du anpassar produktionen som genereras av NSLog för att felsöka program mer effektivt. Läs vidare!


Problem

Som standard visar NSLog utdata i följande format:

 Datum Tid OurApp [] NSLog-utgång

Ett verkligt exempel kan se ut så här:

 2013-08-03 00: 35: 53.038 TestApp [460: c07] Värdet av resultatet = 20

Standardutgången är bra, men det lämnar något att önska. För det mesta vill vi se följande i ett loggutdrag:

  • Namn på källfilen där NSLog () heter
  • Källkodslinjenummer där NSLog () kallades
  • Namn på klassen och metoden där NSLog () kallades
  • Dölj datumstämpel, programnamn och processidentifikationsinfo
  • Aktivera / inaktivera logginformation genom att ändra läge (t ex debug, release, staging)

Kort sagt, vi skulle vilja att NSLog skulle bli mer så här:

 (ClassName MethodName) (SourceFileName: LineNumber) NSLog-utdata

Lösning

Låt oss först titta på hur NSLog fungerar oförändrat. NSLog är bara en C-funktion som är inbyggd i grundramen för kakao, och beter sig som vilken annan variadisk C-funktion som helst. Specifikt skickar NSLog felmeddelanden till Apples systemloggfacilitet. Det gör det enkelt genom att vidarebefordra sina argument till NSLogv-funktionen.

Eftersom NSLog bara är en wrapper för NSLogv, kan vi omdefiniera NSLog med vårt eget samtal till NSLogv. Det är precis vad jag ska visa dig hur man gör i den här handledningen.


1. Starta ett nytt projekt

Skapa ett nytt iOS-projekt i Xcode, med Tom applikation mall. Kalla det ExtendNSLog. Kontrollera alternativet för automatisk referensräkning, men avmarkera alternativen för kärndata och enhetstester.

Skapa ett iOS-projekt med den tomma applikationsmallen Produktnamnet ska vara "ExtendNSLog"

2. Skapa en mål-C-klass

Skapa nu en headerfil tillsammans med projektet. Välj Ny fil> Objektiv - C-klass. Ange klassens namn till ExtendNSLogFunctionality. vilket kommer att bli en underklass av NSObject.

Skapa en objektiv - C-klassmall Ange klassnamnet till ExtendNSLogFunctionality

3. Lägg till anpassad NSLog Logic

Steg 1

Öppna ExtendNSLogFunctionality.h och ange följande kod inom rubriken:

 #importera  #ifdef DEBUG #define NSLog (args ...) ExtendNSLog (__ FIL __, __ LINE __, __ PRETTY_FUNCTION __, args); #else #define NSLog (x ...) #endif void ExtendNSLog (const char * fil, int lineNumber, const char * funktionName, NSString * format, ...);

Ovanstående villkorlig vilja definierar en NSLog uttalande endast när DEBUG är definierad. När DEBUG inte är definierad gör NSLog-satsen ingenting. Frågan uppstår: Hur kontrollerar du när DEBUG är definierad? Detta kan göras genom att tilldela DEBUG = 1 i förprocessorinställningarna för ditt projekt.

För att göra det, klicka på ditt programmål och välj fliken Bygginställningar. Kontrollera sedan att alternativen "Alla" och "Kombinerade" är markerade. Sök efter "preprocessing" och leta reda på avsnittet "Preprocessor Macros". Sedan lägger du helt enkelt till "DEBUG = 1" till Debug-sektionen.

Lägg till DEBUG = 1-flaggan till preprocessorinställningarna

Observera att i senare Xcode-projektmallar finns det redan ett DEBUG = 1-makro som definierats för konfigurationen av Debug build i avsnittet Preprocessor Macros. För mer information, se detta inlägg på StackOverflow.

Steg 2

Med felsökningsmakroen definierad, är vår nästa uppgift att skriva den anpassade versionen av NSLog. Öppna ExtendNSLogFunctionality.m och lägg till följande kod:

 #import "ExtendNSLogFunctionality.h" void ExtendNSLog (const char * fil, int lineNumber, const char * funktionName, NSString * format, ...) // Typ för att hålla information om variabla argument. va_list ap; // Initiera en variabel argumentlista. va_start (ap, format); // NSLog lägger bara till en ny linje till slutet av NSLog-formatet om // en inte redan finns. // Här använder vi denna funktion av NSLog () om (! [Format hasSuffix: @ "\ n"]) format = [format stringByAppendingString: @ "\ n"];  NSString * body = [[NSString allokera] initWithFormat: formatargument: ap]; // Slut med att använda variabel argumentlista. va_end (ap); NSString * fileName = [[NSString stringWithUTF8String: fil] lastPathComponent]; fprintf (stderr, "(% s) (% s:% d)% s", funktionName, [filnamn UTF8String], lineNumber, [body UTF8String]); 

Steg 3

Lägg nu till ExtendNSLogFunctionality.h inkludera prefixrubrikfilen Prefix.pch inom avsnittet #ifdef __OBJC__.

 #ifdef __OBJC__ #import  #importera  #import "ExtendNSLogFunctionality.h" #endif

För en bättre förståelse av prefixrubriker, kolla in den här posten på Wikipedia. När det gäller prefixrubrikens bästa praxis, kolla in det här StackOverflow-inlägget.


4. Ett anpassat loggexempel

Lägg nu till en NSLog var som helst i din projektkod. I mitt fall bestämmer jag att lägga till en inom AppDelegate.ms-metod -(BOOL) ansökan: (UIApplication *) ansökan gjordeFinishLaunchingWithOptions: (NSDictionary *) launchOptions.

 int resultat = 20; NSLog (@ "Resultatvärde:% d", resultat);

Om du bygger och kör projektet med Debug-konfigurationen nu borde du se något så här:

 (- [AppDelegate ansökan: didFinishLaunchingWithOptions:]) (AppDelegate.m: 21) Resultatets värde: 20

Skål! Denna utmatning är mycket mer användbar än standardimplementeringen. Förhoppningsvis finner du att den här tekniken kommer att spara mycket tid medan du felsöker dina egna program!