Devo disabilitare NSLog prima di rilasciare l'applicazione?


117

Quando rilasci un'app per iPhone, se la disabilito NSLog();funzionerà meglio?


1
Nel mio progetto attuale utilizzo UALogger . Non accede alla produzione , se non lo chiedi esplicitamente. E ha altri vantaggi rispetto al normale NSLog come i livelli di gravità (con DEBUG , INFO e così via) pronti all'uso . Buon lavoro!
Anton Gaenko

1
Per rispondere alla tua domanda su "funzionerà meglio?" Sì, ma il rendimento che ottieni dipende da quanti NSLog()ne hai nella tua app. NSLog()richiede tempo per l'esecuzione e aggiunge ulteriore sovraccarico al runtime della tua app. Ad ogni modo, se aiuta nelle prestazioni con una semplice macro del preprocessore DEBUG, allora dovremmo disabilitarlo.
Scott

Suggerirei anche se hai molte istruzioni NSLog / print nel tuo codice, potrebbe suggerirti di dedicare un po 'di tempo a imparare di più sul debugger. Ho impostato regolarmente punti di interruzione che stampano le informazioni che mi interessano e continuo automaticamente. Sì, può rallentare un po 'la corsa, ma nella maggior parte dei casi non è opprimente. Inoltre, interruzioni condizionali in modo da poter indagare quando è accaduto qualcosa di inaspettato.
bshirley

Risposte:


127

Un modo per farlo è accedere alle impostazioni di compilazione e nella configurazione di debug aggiungere un valore al valore "Macro del preprocessore" come:

DEBUG_MODE=1

Assicurati di farlo solo per la configurazione di debug e non per le versioni Beta o Release. Quindi in un file di intestazione comune puoi fare qualcosa come:

#ifdef DEBUG_MODE
#define DLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSString stringWithUTF8String:__FILE__] lastPathComponent], __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__] )
#else
#define DLog( s, ... ) 
#endif

Ora invece di NSLog usarlo DLogovunque. Durante il test e il debug, riceverai messaggi di debug. Quando sei pronto per rilasciare una versione beta o finale, tutte quelle DLogrighe diventano automaticamente vuote e non viene emesso nulla. In questo modo non è possibile impostare manualmente le variabili o commentare i NSLogsrequisiti. Scegliere il tuo obiettivo di costruzione si prende cura di tutto ciò.


In Xcode 4.5 fornisce un avviso che dice: "La dichiarazione implicita della funzione 'DLog' non è valida in C99", quindi questa cosa non funziona.
Sergey Grischyov

2
@SergiusGee: ricevi l'avviso di dichiarazione implicita se la dichiarazione per la funzione non può essere trovata, nel qual caso si pensa che tu stia cercando di dichiararla. Assicurati che la tua classe abbia accesso al file di intestazione in cui è dichiarato.
sudo rm -rf

1
Non voglio disconnetterti in quanto ti priva della possibilità di ricevere rapporti di errore migliori dagli utenti. usa la registrazione asincrona e logLevels per limitare il calo delle prestazioni quasi a zero! (vedi il boscaiolo di cacao o il log4j di java
Daij-Djan

2
Preferirei #if piuttosto che #ifdef, poiché DEBUG_MODE 0 seguirà ancora il vero percorso
Grady Player

1
questo non risponde alla domanda
Martin Mlostek

117

Aggiornamento per Xcode 5 e iOS 7

nota: per una soluzione Xcode 7 / Swift 2.1 per rimuovere le istruzioni print () in una build di rilascio, trova la mia risposta qui .

Sì, dovresti rimuovere qualsiasi istruzione NSLog nel codice di rilascio, poiché rallenta semplicemente il codice e non è di alcuna utilità in una versione di rilascio. Fortunatamente, in Xcode 5 (iOS 7), è incredibilmente semplice rimuovere "automaticamente" tutte le istruzioni NSLog nelle build di rilascio. Allora perché non farlo.

Prima i 3 passaggi da compiere, poi alcune spiegazioni

1) nel tuo progetto Xcode, individua il file 'yourProjectName-prefix.pch' (normalmente lo troverai nel gruppo 'file di supporto', dove si trova il tuo file main.m

2) aggiungi queste 3 righe alla fine del file ".pch":

#ifndef DEBUG
   #define NSLog(...);
#endif

3) prova la differenza tra la tua versione "debug" e "release". Un modo per farlo è tramite "modifica schema" -> "esegui nome app" -> nella scheda "informazioni" selezionare utilizzando la casella a discesa tra debug e rilascio. Nella versione di rilascio non vedrai alcun output NSLog nella console di debug!

Come funziona tutto ciò?

prima di tutto, bisogna sapere che un preprocessore è relativamente "stupido" e agisce semplicemente come un "sostituto di testo" prima che il compilatore venga chiamato. Sostituisce tutto ciò che "#define" con ciò che segue la #definedichiarazione.

#define NSLog(...);

Il (...)sta per "qualsiasi cosa" tra le parentesi (). Attenzione anche ;alla fine. Questo non è strettamente necessario poiché il compilatore lo ottimizzerà, ma mi piace metterlo lì, poiché è più "corretto". Dopo il nostro #definenon c'è "niente", quindi il preprocessore lo sostituirà con "niente", e quindi butterà via la riga completa, a partire da NSLog...fino a quando includerà il file ;.

le dichiarazioni di definizione possono essere condizionate usando #ifdef(se definito) o #ifndef(se non definito)

qui scriviamo #ifndef DEBUG, che significa 'se il simbolo DEBUG non è definito'. Il #ifdefo #ifndefdeve essere "chiuso" con#endif

Xcode 5 definisce di default il simbolo "DEBUG" quando la modalità di de build è "DEBUG". In "release" questo non è definito. puoi verificarlo nelle impostazioni del tuo progetto, scheda "Impostazioni build" -> scorri verso il basso fino alla sezione "Apple LLVM 5.0 - Preprocessing" -> macro del preprocessore. Vedrai che il simbolo "DEBUG" non è definito per le build di rilascio!

infine, il file .pch viene creato automaticamente da Xcode e automaticamente incluso in ogni file sorgente durante il tempo di compilazione. Quindi è come se avessi messo tutto #definein ciascuno dei tuoi file sorgente.


1
Grazie @Whasssaaahhh, funziona alla grande. Fare attenzione a evitare di inserire codice nelle istruzioni di registro! Il preprocessore rimuoverà tutte le NSLogistruzioni ignorando ciò che è all'interno.
Eric Platon

1
Se si tratta di un progetto più vecchio che non ha il flag di debug nelle macro del preprocessore, è importante aggiungere "debug = 1" per il progetto e non per il target
Priebe

1
Inoltre, non utilizzare NSLogcome affermazione non fare nulla, ad esempio, if(AllCool) NSLog(@"Cool!Do Nothing!"); else...invece NSLogif(AllCool) {NSLog(@"Cool!Do Nothing!");} else...
inserire

33

Quasi tutte le risposte precedenti suggeriscono una soluzione ma non spiegano il problema. Ho fatto una ricerca su google e ho trovato il motivo. Ecco la mia risposta:

Sì, se commentate NSLog nella versione di rilascio, le prestazioni miglioreranno. Perché NSLog è piuttosto lento. Perché? NSLog farà due cose: 1) scrive i messaggi di log in Apple System Logging (ASL), 2) se l'app viene eseguita in xcode, scrive anche su stderr.

Il problema principale risiede nel primo. Per ottenere thread safe, ogni volta che viene chiamato NSLog, apre una connessione alla struttura ASL , invia un messaggio e chiude la connessione. L'operazione di connessione è molto costosa. Un altro motivo è che NSLog impiega del tempo per ottenere il timestamp da registrare.

Riferimento da qui .


23

Il mio preferito è usare una macro variadica.

#ifdef NDEBUG
    #define NSLog(...) /* suppress NSLog when in release mode */
#endif

1
Dove lo metti?
user6631314

20

Oltre a tutte le persone che hanno saggiamente commentato che non chiamare NSLog()affatto in produzione è leggermente più veloce, aggiungo che:

Tutte queste NSLog()stringhe di output sono visibili a chiunque scarichi la tua app dallo store e la esegua con il dispositivo collegato a un Mac che esegue Xcode (tramite la finestra Organizer).

A seconda delle informazioni che registri (e soprattutto se la tua app contatta un server, esegue l'autenticazione, ecc.), Questo può essere un serio problema di sicurezza .


grazie per le informazioni - è nel documento da qualche parte o l'hai scoperto tu stesso? È ancora vero per la stampa in Swift?
Ronny Webers

Non ricordo di aver letto alcuna documentazione. Ho appena installato la mia build archiviata (lo stesso binario che ho inviato allo store) sul mio dispositivo e l'ho collegato a Xcode. Non ho idea se sia lo stesso per Swift print(), ma molto probabilmente lo è.
Nicolas Miari

@NicolasMiari Cosa intendi per collegato a Xcode? Come possiamo collegare il nostro binario a Xcode, in realtà voglio provare lo stesso. Quindi per favore suggerisci. Grazie.
iDevAmit

@iDeveloper Intendo scaricare la tua app dall'AppStore su un dispositivo (ad esempio, un iPhone), collega quel dispositivo a Xcode tramite USB, avvia la tua app e guarda i log nella finestra "Dispositivi" di Xcode.
Nicolas Miari

3
@Whasssaaahhh print non viene visualizzato nella console del dispositivo .. l'ho appena testato
Anish Parajuli 웃

13

Impostazione predefinita del progetto

All'interno dell'impostazione predefinita corrente del progetto in Xcode, la NS_BLOCK_ASSERTIONSmacro sarà impostata su 1 nella versione di rilascio e DEBUG=1nella versione di debug.

Quindi, preferisco il seguente metodo.

// NS_BLOCK_ASSERTIONS is defined by default, as shown in the screenshot above.
// Or, you can define yourself Flags in the `Other C Flags` -> `Release`.
#ifndef NS_BLOCK_ASSERTIONS
    #define _DEBUG
#endif

#ifdef _DEBUG
// for debug mode 
#define DLog(fmt,...) NSLog(@"%s " fmt, __FUNCTION, ##__VA_ARGS__) 
... /// something extra
#else
// for release mode
#define DLog(fmt,...) /* throw it away */
... /// something extra
#endif

5

Sì, dovresti disabilitarlo. Soprattutto se stai cercando di massimizzare la velocità del tuo codice. NSLogging di cose a destra ea sinistra inquina il registro di sistema che altri sviluppatori potrebbero cercare di scavare e può avere un grande impatto sul codice critico per la velocità (all'interno di cicli, ecc.) Ho accidentalmente lasciato alcuni messaggi di registro in una funzione ricorsiva una volta e ha rilasciato un aggiornamento con un "aumento della velocità del 30%!" qualche settimana dopo... ;-)


5

Tutte buone risposte, tuttavia ecco un altro piccolo trucco che puoi considerare di utilizzare, principalmente nelle fasi di sviluppo / test della tua app.

Potrebbe anche essere utile anche per il codice di rilascio dell'app, se desideri disattivare solo il TUO codice di debug e non i messaggi che potrebbero indicare problemi al di fuori del controllo diretto del tuo codice.

Il trucco:

Puoi disattivare NSLog per file .m semplicemente includendo la seguente riga nella parte superiore del file .m :

#define NSLog(...)

( NOTA: NON inserire questo file .h, solo il file .m! )

Questo fa sì che il compilatore valuti NSLog()espandendo invece la macro del preprocessore. La macro non fa altro che eliminare gli argomenti.

se vuoi riaccenderlo puoi sempre usare

#undef NSLog

Ad esempio, potresti semplicemente impedire le chiamate a NSLog attorno a un particolare gruppo di metodi facendo qualcosa di simile

#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
    ...
}
#undef NSLog

3

NSLog è lento e non deve essere utilizzato per le build di rilascio. Una semplice macro come quella qui sotto la disabiliterà insieme a qualsiasi asserzione che potresti avere che dovrebbe essere disabilitata. Nel caso meno comune in cui desideri NSLog in una build di rilascio, chiamalo direttamente. Non dimenticare di aggiungere "-DNDEBUG" alle impostazioni di compilazione degli "altri flag c".

#ifdef NDEBUG
#define MYLog(f, ...) 
#else
#define MYLog(f, ...) NSLog(f, ## __VA_ARGS__)
#endif


0

che dire di questo?

#ifndef DEBUG_MODE
        fclose(stderr);     // the simplest way to disable output from NSLog
#endif    

1
questo disabilita l'output, ma non risparmia tempo di elaborazione, ad esempio NSLog viene ancora chiamato ei suoi argomenti analizzati
dwery

0
var showDebugLogs = false;

    func DLog(format: String, args: CVarArgType...) {
        if showDebugLogs{
        println(String(format: format, arguments: args))
        }
    }

Questo accetterà anche gli argomenti aggiuntivi .. Solo il valore del parametro showDebugLogs su true o false, secondo le tue necessità


Questo è carino, ma ha ancora il problema di tutto il sovraccarico delle chiamate e di qualsiasi sovraccarico (e potenziali effetti collaterali) del calcolo di qualsiasi argomento passato alla Dlogfunzione.
Todd Lehman
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.