Dois-je désactiver NSLog avant de lancer l'application?

117

Lorsque je publie une application pour iPhone, si je la désactive, NSLog();est-ce qu'elle fonctionnera mieux?

RAGOPOR
la source
1
Dans mon projet actuel, j'utilise UALogger . Il ne se connecte pas à la production , si vous ne le demandez pas explicitement. Et a d'autres avantages par rapport à NSLog standard tels que les niveaux de gravité (avec DEBUG , INFO , etc.) prêts à l'emploi . Bon travail!
Anton Gaenko le
1
Pour répondre à votre question sur "sera-t-il plus performant?" Oui, mais le rendement que vous obtenez dépend du nombre dont NSLog()vous disposez dans votre application. NSLog()prend du temps à s'exécuter et ajoute une surcharge supplémentaire à l'exécution de votre application. Quoi qu'il en soit, si cela améliore les performances avec une simple macro de préprocesseur DEBUG, nous devrions la désactiver.
Scott
Je suggérerais également que si vous avez beaucoup d'instructions NSLog / print dans votre code, cela pourrait suggérer que vous devriez passer du temps à en apprendre davantage sur le débogueur. Je fixe régulièrement des points d'arrêt qui impriment les informations qui m'intéressent, et je continue automatiquement. Oui, cela peut ralentir un peu la course, mais dans la plupart des cas, ce n'est pas écrasant. En outre, des pauses conditionnelles vous permettent d'enquêter sur les événements inattendus.
bshirley

Réponses:

127

Une façon de le faire est d'aller dans vos paramètres de construction et sous la configuration de débogage, ajoutez une valeur à la valeur "Macros de préprocesseur" comme:

DEBUG_MODE=1

Assurez-vous de ne faire cela que pour la configuration de débogage et non pour les versions Beta ou Release. Ensuite, dans un fichier d'en-tête commun, vous pouvez faire quelque chose comme:

#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

Maintenant au lieu de l' NSLog utiliser DLogpartout. Lors du test et du débogage, vous recevrez des messages de débogage. Lorsque vous êtes prêt à publier une version bêta ou finale, toutes ces DLoglignes deviennent automatiquement vides et rien n'est émis. De cette façon, il n'y a pas de réglage manuel des variables ou de commentaire de NSLogsrequis. Le choix de votre cible de construction s'en occupe.

Ramin
la source
Dans Xcode 4.5, il donne un avertissement qui dit: "La déclaration implicite de la fonction 'DLog' n'est pas valide en C99" donc cette chose ne fonctionne pas.
Sergey Grischyov
2
@SergiusGee: Vous obtenez l'avertissement de déclaration implicite si la déclaration de la fonction est introuvable, auquel cas il pense que vous essayez de la déclarer. Assurez-vous que votre classe a accès au fichier d'en-tête où cela est déclaré.
sudo rm -rf
1
Je ne souhaite pas vous déconnecter car cela vous prive de la possibilité de recevoir de meilleurs rapports d'erreur des utilisateurs. utilisez la journalisation asynchrone et les logLevels pour limiter les performances à presque zéro! (voir cacao bûcheron ou java's log4j
Daij-Djan
2
J'irais avec #if plutôt que #ifdef, car DEBUG_MODE 0 suivra toujours le vrai chemin
Grady Player
1
cela ne répond pas à la question
Martin Mlostek
117

Mise à jour pour Xcode 5 et iOS 7

note: pour une solution Xcode 7 / Swift 2.1 pour supprimer les instructions print () dans une version de version, trouvez ma réponse ici .

Oui, vous devez supprimer toute instruction NSLog dans votre code de version, car elle ralentit simplement votre code et n'est d'aucune utilité dans une version de publication. Heureusement, dans Xcode 5 (iOS 7), il est incroyablement simple de supprimer toutes vos instructions NSLog `` automatiquement '' dans les versions de version. Alors pourquoi ne pas le faire.

D'abord les 3 étapes à suivre, puis quelques explications

1) dans votre projet Xcode, localisez le fichier 'yourProjectName-prefix.pch' (normalement vous le trouverez sous le groupe 'support files', où se trouve votre fichier main.m

2) ajoutez ces 3 lignes à la fin du fichier '.pch':

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

3) testez la différence entre votre version «debug» et «release». Une façon de le faire consiste à utiliser 'modifier le schéma' -> 'exécuter le nom de l'application' -> sous l'onglet 'info', sélectionnez en utilisant la liste déroulante entre le débogage et la publication. Dans la version finale, vous ne verrez aucune sortie NSLog dans la console de débogage!

Comment ça marche?

tout d'abord, il faut savoir qu'un préprocesseur est relativement «stupide», et agit simplement comme un «remplaçant de texte» avant que le compilateur ne soit appelé. Il remplace tout ce que vous '#define' par ce qui suit l' #defineinstruction.

#define NSLog(...);

Le (...)signifie «n'importe quoi» entre les crochets (). Attention aussi ;à la fin. Ce n'est pas strictement nécessaire car le compilateur optimisera cela, mais j'aime le mettre là, car il est plus «correct». Après notre #defineil n'y a «rien», donc le préprocesseur le remplacera par «rien», et ainsi il jettera simplement la ligne complète, en commençant par NSLog...jusqu'à et y compris le ;.

Les instructions define peuvent être rendues conditionnelles en utilisant #ifdef(si défini) ou #ifndef(si non défini)

ici nous écrivons #ifndef DEBUG, ce qui signifie «si le symbole DEBUG n'est pas défini». Le #ifdefou #ifndefdoit être `` fermé '' avec#endif

Xcode 5 définit par défaut le symbole 'DEBUG' pour nous lorsque le mode de construction est 'DEBUG'. Dans «release», cela n'est pas défini. vous pouvez le vérifier dans les paramètres de votre projet, onglet 'Paramètres de construction' -> faites défiler jusqu'à la section 'Apple LLVM 5.0 - Prétraitement' -> macros de préprocesseur. Vous verrez que le symbole «DEBUG» n'est pas défini pour les versions de version!

enfin, le fichier .pch est créé automatiquement par Xcode, et automatiquement inclus dans chaque fichier source pendant la compilation. C'est comme si vous aviez mis le tout #definedans chacun de vos fichiers source.

Ronny Webers
la source
1
Merci @Whasssaaahhh, cela fonctionne très bien. Faites attention à ne pas mettre de code dans les instructions de journal! Le préprocesseur supprimera toutes les NSLoginstructions sans tenir compte de ce qui se trouve à l'intérieur.
Eric Platon
1
Si c'est un projet plus ancien qui n'a pas l'indicateur de débogage dans les macros de préprocesseur, il est important d'ajouter le "debug = 1" pour le projet et non la cible
Priebe
1
De plus, ne l'utilisez pas NSLogcomme une instruction ne rien faire, par exemple, if(AllCool) NSLog(@"Cool!Do Nothing!"); else...NSLogif(AllCool) {NSLog(@"Cool!Do Nothing!");} else...
placez
33

Presque toutes les réponses ci-dessus suggèrent une solution mais n'expliquent pas le problème. J'ai fait une recherche sur google et j'ai trouvé la raison. Voici ma réponse:

Oui, si vous commentez NSLog dans votre version, les performances seront meilleures. Parce que NSLog est assez lent. Pourquoi? NSLog fera deux choses 1) écrire des messages de journal dans Apple System Logging (ASL), 2) si l'application s'exécute dans xcode, elle écrit également dans stderr.

Le problème principal réside dans le premier. Afin de garantir la sécurité des threads, chaque fois que NSLog est appelé, il ouvre une connexion à la fonction ASL , envoie un message et ferme la connexion. L'opération de connexion est très coûteuse. Une autre raison est que NSLog passe un certain temps à obtenir l'horodatage à enregistrer.

Référence d' ici .

Andrew
la source
23

Mon préféré est d'utiliser une macro variadique.

#ifdef NDEBUG
    #define NSLog(...) /* suppress NSLog when in release mode */
#endif
Eytan
la source
1
Où mettez-vous cela?
user6631314
20

En plus de toutes les personnes qui ont sagement commenté que ne pas appeler NSLog()du tout en production fonctionnait un peu plus vite, j'ajouterai que:

Toutes ces NSLog()chaînes de sortie sont visibles par toute personne qui télécharge votre application à partir du magasin et l'exécute avec l'appareil branché sur un mac exécutant Xcode (via la fenêtre de l'organiseur).

En fonction des informations que vous consignez (et surtout si votre application contacte un serveur, effectue une authentification, etc.), cela peut être un problème de sécurité sérieux .

Nicolas Miari
la source
merci pour l'info - est-ce quelque part dans le document ou vient-il de le découvrir vous-même? Est-ce toujours vrai pour l'impression dans Swift?
Ronny Webers
Je ne me souviens pas avoir lu de documentation. Je viens d'installer ma version archivée (le même binaire que j'ai soumis au magasin) sur mon appareil et je l'ai connectée à Xcode. Je ne sais pas si c'est la même chose pour Swift print(), mais c'est probablement le cas.
Nicolas Miari
@NicolasMiari Qu'entendez-vous par branché sur Xcode? Comment nous pouvons brancher notre binaire dans Xcode, en fait, je veux essayer la même chose. Alors veuillez suggérer. Merci.
iDevAmit le
@iDeveloper Je veux dire télécharger votre application depuis l'AppStore sur un appareil (par exemple, un iPhone), branchez cet appareil à Xcode via USB, lancez votre application et regardez les journaux dans la fenêtre «Appareils» de Xcode.
Nicolas Miari
3
L'impression @Whasssaaahhh ne s'affiche pas dans la console de l'appareil..Je viens de le tester
Anish Parajuli 웃
13

Paramètre par défaut du projet

Dans le paramètre par défaut actuel du projet dans Xcode, la NS_BLOCK_ASSERTIONSmacro sera définie sur 1 dans la version commerciale et DEBUG=1dans la version Debug.

Donc, je préfère la méthode suivante.

// 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
AechoLiu
la source
5

Oui, vous devez le désactiver. Surtout si vous essayez de maximiser la vitesse de votre code. NSLogging à gauche et à droite pollue le journal système que d'autres développeurs pourraient essayer de fouiller et cela peut avoir un impact important sur le code à vitesse critique (boucles internes, etc.) J'ai accidentellement laissé des messages de journal dans une fonction récursive une fois et obtenu de publier une mise à jour avec une "augmentation de vitesse de 30%!" quelques semaines plus tard... ;-)

Ben Gotow
la source
5

Toutes les bonnes réponses, cependant, voici une autre petite astuce que vous pouvez envisager d'utiliser, principalement dans les phases de développement / test de votre application.

Cela peut également être utile pour le code de version d'application, si vous souhaitez uniquement désactiver VOTRE code de débogage, et non les messages qui pourraient indiquer des problèmes en dehors du contrôle direct de votre code.

L'astuce:

Vous pouvez désactiver NSLog par fichier .m en incluant simplement la ligne suivante en haut du fichier .m :

#define NSLog(...)

( REMARQUE: ne placez PAS ce fichier .h, seulement le fichier .m! )

Cela permet simplement au compilateur d'évaluer NSLog()en développant votre macro de préprocesseur à la place. La macro ne fait rien d'autre que supprimer les arguments.

si vous souhaitez le réactiver, vous pouvez toujours utiliser

#undef NSLog

Vous pouvez par exemple simplement empêcher les appels à NSLog autour d'un groupe particulier de méthodes en faisant quelque chose comme

#define NSLog(...)
-(void) myProblematicMethodThatSometimesNeedsDebugging {
    ...
}
#undef NSLog
non synchronisé
la source
3

NSLog est lent et ne doit pas être utilisé pour les versions de version. Une simple macro comme celle ci-dessous la désactivera avec toutes les assertions que vous pourriez avoir et qui devraient également être désactivées. Dans le cas moins courant où vous voulez NSLog dans une version de version, appelez-le directement. N'oubliez pas d'ajouter "-DNDEBUG" à vos paramètres de construction "autres indicateurs c".

#ifdef NDEBUG
#define MYLog(f, ...) 
#else
#define MYLog(f, ...) NSLog(f, ## __VA_ARGS__)
#endif
papahabla
la source
2

dans le fichier pch, écrivez ceci avant #endif

#define NSLog() //
Sandeep Saurabh
la source
0

Et ça?

#ifndef DEBUG_MODE
        fclose(stderr);     // the simplest way to disable output from NSLog
#endif    
roberto.buratti
la source
1
cela désactive la sortie, mais n'économise pas de temps de traitement, c'est-à-dire que NSLog est toujours appelé et ses arguments analysés
dwery
0
var showDebugLogs = false;

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

Cela acceptera également les arguments supplémentaires. Juste la valeur du paramètre showDebugLogs à true ou false, selon vos besoins

Zahur
la source
C'est bien, mais cela pose toujours le problème de toute la surcharge d'appel et de toute surcharge (et effets secondaires potentiels) du calcul des arguments passés à la Dlogfonction.
Todd Lehman