Sfat rapid Personalizați NSLog pentru o depanare mai ușoară

În acest sfat rapid vom învăța cum să customizăm ieșirea generată de NSLog pentru a debuga mai eficient programele. Citește mai departe!


Problemă

În mod implicit, NSLog afișează ieșirea în următorul format:

 Data Ora OurApp [] Ieșire NSLog

Un exemplu din lumea reală poate arăta astfel:

 2013-08-03 00: 35: 53.038 TestApp [460: c07] Valoarea rezultatului = 20

Ieșirea implicită este bună, dar lasă ceva de dorit. De cele mai multe ori, vrem să vedem următoarele într-o declarație a jurnalului:

  • Numele fișierului sursă unde a fost apelat NSLog ()
  • Numărul liniei de cod sursă unde a fost apelat NSLog ()
  • Numele clasei și metodei în care a fost apelat NSLog ()
  • Ascunde ștampila cu data, numele aplicației și informațiile despre proces
  • Activați / dezactivați informațiile din jurnal prin modificarea modului (de exemplu, depanare, eliberare, staționare)

Pe scurt, dorim ca NSLog să fie mai mult ca acesta:

 (NumeleNamei de clasăName) (SourceFileName: LineNumber) ieșire NSLog

Soluţie

Să aruncăm o privire asupra modului în care NSLog funcționează nealterată. NSLog este doar o funcție C construită în cadrul fundației Cocoa și se comportă ca orice altă funcție variadic C. În mod specific, NSLog trimite mesaje de eroare la facilitatea Jurnal de sistem Apple. Aceasta face acest lucru pur și simplu prin transmiterea argumentelor sale de-a lungul funcției NSLogv.

Deoarece NSLog este doar un pachet pentru NSLogv, putem redefini NSLog cu apelul personalizat la NSLogv. Asta este exact ceea ce vă voi arăta cum să faceți acest tutorial.


1. Începeți un nou proiect

Creați un nou proiect iOS în Xcode, împreună cu Cerere goală șablon. Sună-l ExtendNSLog. Verificați opțiunea pentru numărarea automată a referințelor, dar debifați opțiunile pentru datele de bază și testele de unitate.

Creați un proiect iOS cu șablonul Cerere goală Numele produsului ar trebui să fie "ExtendNSLog"

2. Creați o clasă obiectiv-C

Acum creați un fișier antet împreună cu proiectul. Selectați Fișier nou> Obiectiv - Clasa C. Setați numele clasei la ExtendNSLogFunctionality. care va fi o subclasă a NSObject.

Creați un șablon de clasă obiectiv - C Setați numele clasei la ExtendNSLogFunctionality

3. Adăugați Logica personalizată NSLog

Pasul 1

Deschis ExtendNSLogFunctionality.h și plasați următorul cod în antet:

 #import  #ifdef DEBUG #define NSLog (args ...) ExtendNSLog (__FILE __, __LINE __, __ PRETTY_FUNCTION __, args); #else #define NSLog (x ...) #endif void ExtendNSLog (const char * fișier, int lineNumber, const char * functionName, format NSString *, ...);

Condiționarea de mai sus va defini o NSLog declarație numai atunci când DEBUG este definită. Când DEBUG nu este definită, instrucțiunea NSLog nu va face nimic. Se pune întrebarea: cum controlați când este definită DEBUG? Acest lucru se poate face prin atribuirea DEBUG = 1 în setările de preprocesor pentru proiectul dvs..

Pentru aceasta, faceți clic pe destinația aplicației dvs. și selectați fila Setări pentru configurare. Apoi, asigurați-vă că sunt selectate opțiunile "Toate" și "Combinate". Căutați "preprocesare" și găsiți secțiunea intitulată "Macrocomenzi preprocesor". Apoi, pur și simplu adăugați "DEBUG = 1" la secțiunea Debug.

Adăugați parametrul DEBUG = 1 în setările preprocesorului

Rețineți că în șabloanele de proiecte Xcode mai recente, va exista deja o macrocomandă DEBUG = 1 definită pentru configurația de configurare a Debug din secțiunea Macroprocesoare. Pentru mai multe informații, consultați acest post pe StackOverflow.

Pasul 2

Cu macrocomanda de depanare definită, următoarea noastră sarcină este să scriem versiunea personalizată a NSLog. Deschideți ExtendNSLogFunctionality.m și adăugați următorul cod:

 #import "ExtendNSLogFunctionality.h" void ExtendNSLog (const char * fișier, int lineNumber, const char * functionName, format NSString *, ...) // Introduceți informații despre argumentele variabile. va_list ap; // Inițializați o listă de variabile de argumente. va_start (ap, format); // NSLog adaugă doar un nou rând la sfârșitul formatului NSLog dacă // nu este deja acolo. // Aici folosim această caracteristică a NSLog () dacă (! [Format hasSuffix: @ "\ n"]) format = [format stringByAppendingString: @ "\ n"];  NSString * body = [[NSString aliniere] initWithFormat: argumente de format: ap]; // Terminați folosind lista de argumente variabile. va_end (ap); NSString * fileName = [[NSString stringWithUTF8String: fișier] lastPathComponent]; fprintf (stderr, "(% s) (% s:% d)% s", funcțiaName, [fileName UTF8String], lineNumber, [body UTF8String]); 

Pasul 3

Acum adăugați extensia ExtendNsLogFunctionality.h în fișierul Prefix.pch din antetul prefixului în secțiunea #ifdef __OBJC__.

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

Pentru a înțelege mai bine antetele prefixelor, aruncați o privire la această intrare pe Wikipedia. În ceea ce privește cele mai bune practici privind antetul prefixului, consultați acest post StackOverflow.


4. Un exemplu de jurnal personalizat

Acum adăugați un NSLog oriunde în codul dvs. de proiect. În cazul meu, am decis să adaug una în cadrul metodei lui AppDelegate.m -(BOOL): aplicație (UIApplication *) didFinishLaunchingWithOptions: (NSDictionary *) launchOptions.

 int rezultat = 20; NSLog (@ "Valoarea rezultatului:% d", rezultat);

Dacă construiți și rulați proiectul acum cu configurația Debug, ar trebui să vedeți ceva de genul:

 (- Aplicație AppDelegate: didFinishLaunchingWithOptions:]) (AppDelegate.m: 21) Valoarea rezultatului: 20

Noroc! Această ieșire este mult mai utilă decât implementarea implicită. Sperăm că veți descoperi că această tehnică vă va economisi mult timp în timpul depanării programelor proprii!

Cod