Est-il vrai que l’on ne doit pas utiliser NSLog () sur du code de production?

On m’a dit ça à quelques resockets sur ce même site, mais je voulais m’assurer que c’était vraiment le cas.

Je m’attendais à pouvoir saupoudrer les appels de fonction NSLog dans mon code, et que Xcode / gcc supprime automatiquement ces appels lors de la construction de mes versions Release / Dissortingbution.

Devrais-je éviter d’utiliser cela? Si oui, quelles sont les alternatives les plus courantes entre les programmeurs Objective-C expérimentés?

Les macros de préprocesseur sont en effet très utiles pour le débogage. Il n’y a rien de mal à NSLog (), mais il est simple de définir votre propre fonction de journalisation avec de meilleures fonctionnalités. Voici celui que j’utilise, il comprend le nom du fichier et le numéro de ligne pour faciliter le suivi des instructions du journal.

#define DEBUG_MODE #ifdef DEBUG_MODE #define DebugLog( s, ... ) NSLog( @"<%p %@:(%d)> %@", self, [[NSSsortingng ssortingngWithUTF8Ssortingng:__FILE__] lastPathComponent], __LINE__, [NSSsortingng ssortingngWithFormat:(s), ##__VA_ARGS__] ) #else #define DebugLog( s, ... ) #endif 

J’ai trouvé plus facile de mettre cette déclaration entière dans l’en-tête de préfixe plutôt que dans son propre fichier. Vous pourriez, si vous voulez, construire un système de journalisation plus compliqué en faisant interagir DebugLog avec des objects Objective-C normaux. Par exemple, vous pouvez avoir une classe de journalisation qui écrit dans son propre fichier journal (ou firebase database) et inclut un argument ‘priority’ que vous pouvez définir lors de l’exécution. Les messages de débogage ne sont donc pas affichés Si vous faites cela, vous pouvez créer DebugLog (), WarningLog (), etc.

Oh, et n’oubliez pas #define DEBUG_MODE peut être réutilisé à différents endroits de votre application. Par exemple, dans mon application, je l’utilise pour désactiver les vérifications de clé de licence et autoriser uniquement l’exécution de l’application si elle est antérieure à une certaine date. Cela me permet de dissortingbuer une copie bêta entièrement fonctionnelle et limitée dans le temps avec un effort minimal de ma part.

Mettez ces 3 lignes à la fin du fichier -prefix.pch:

 #ifndef DEBUG #define NSLog(...) /* suppress NSLog when in release mode */ #endif 

Vous n’avez pas besoin de définir quoi que ce soit dans votre projet, car DEBUG est défini dans votre paramètre de génération par défaut lorsque vous créez votre projet.

Les appels NSLog peuvent être laissés dans le code de production, mais ne doivent être disponibles que dans des cas vraiment exceptionnels ou pour des informations souhaitées qui seront consignées dans le journal système.

Les applications qui encombrent le journal système sont ennuyeuses et ne sont pas professionnelles.

Je ne peux pas commenter la réponse de Marc Charbonneau , alors je posterai cela comme une réponse.

Outre l’ajout de la macro à votre en-tête pré-compilé, vous pouvez utiliser les configurations de génération Target pour contrôler la définition (ou l’absence de définition) de DEBUG_MODE .

Si vous sélectionnez la configuration active ” Debug “, DEBUG_MODE sera défini et la macro se développera à la définition complète de NSLog .

La sélection de la configuration active ” Release ” ne définira pas DEBUG_MODE et votre NSLog ging sera omis de la version de publication.

Pas:

  • Cible> Obtenir des informations
  • Onglet Construire
  • Recherchez “Macros PreProcessor” (ou GCC_PREPROCESSOR_DEFINITIONS )
  • Sélectionnez Configuration: Debug
  • Modifier la définition à ce niveau
  • Ajouter DEBUG_MODE=1
  • Sélectionnez Configuration: Release
  • confirmer que DEBUG_MODE n’est pas défini dans GCC_PREPROCESSOR_DEFINITIONS

Si vous omettez le caractère ‘=’ dans la définition, vous recevrez une erreur du préprocesseur

Aussi, collez ce commentaire (illustré ci-dessous) au-dessus de la définition de la macro pour vous rappeler d’où vient la définition de DEBUG_MACRO 😉

 // Target > Get Info > Build > GCC_PREPROCESSOR_DEFINITIONS // Configuration = Release:  // = Debug: DEBUG_MODE=1 

EDIT: La méthode postée par Marc Charbonneau et scope à ma connaissance par sho est bien meilleure que celle-ci.

J’ai supprimé la partie de ma réponse qui suggère d’utiliser une fonction vide pour désactiver la journalisation lorsque le mode de débogage est désactivé. La partie qui traite de la définition d’une macro de préprocesseur automatique est toujours pertinente, elle l’est toujours. J’ai aussi édité le nom de la macro du préprocesseur pour qu’il corresponde mieux à la réponse de Marc Charbonneau.


Pour obtenir le comportement automatique (et attendu) dans Xcode:

Dans les parameters du projet, accédez à l’onglet “Build” et sélectionnez la configuration “Debug”. Recherchez la section “Macros du préprocesseur” et ajoutez une macro nommée DEBUG_MODE .

EDIT: Voir la réponse de Marc Charbonneau pour savoir comment activer et désactiver la journalisation avec la macro DEBUG_MODE .

Je suis d’accord avec Matthew. Il n’y a rien de mal avec NSLog dans le code de production. En fait, cela peut être utile à l’utilisateur. Cela dit, si la seule raison pour laquelle vous utilisez NSLog est d’aider au débogage, alors, oui, cela devrait être supprimé avant la publication.

De plus, NSLog utilise des ressources, ce que l’iPhone n’a que très peu d’importance. Si vous utilisez NSLogging sur l’iPhone, le temps de traitement de votre application est réduit. Fais-en bon usage.

La simple vérité est que NSLog est tout simplement lent.

Mais pourquoi? Pour répondre à cette question, découvrons ce que fait NSLog, puis comment il le fait.

Que fait NSLog exactement?

NSLog fait 2 choses:

Il écrit les messages de journal dans la fonction de consignation système Apple (asl). Cela permet aux messages de journal de s’afficher dans Console.app. Il vérifie également si le stream stderr de l’application est dirigé vers un terminal (par exemple, lorsque l’application est exécutée via Xcode). Si c’est le cas, il écrit le message de journal sur stderr (pour qu’il apparaisse dans la console Xcode).

Ecrire dans STDERR ne semble pas difficile. Cela peut être accompli avec fprintf et la référence du descripteur de fichier stderr. Mais qu’en est-il asl?

La meilleure documentation que j’ai trouvée sur ASL est un article de Peter Hosey en 10 parties: link

Sans entrer dans trop de détails, le point culminant (en ce qui concerne les performances) est le suivant:

Pour envoyer un message de journal à la fonction ASL, vous ouvrez essentiellement une connexion client au démon ASL et envoyez le message. MAIS – chaque thread doit utiliser une connexion client distincte. Donc, pour être thread-safe, chaque fois que NSLog est appelé, il ouvre une nouvelle connexion client asl, envoie le message et ferme la connexion.

Les ressources peuvent être trouvées ici et ici .

Comme indiqué dans d’autres réponses, vous pouvez utiliser un #define pour déterminer si NSLog est utilisé ou non au moment de la compilation.

Cependant, une méthode plus flexible consiste à utiliser une bibliothèque de journalisation telle que Cocoa Lumberjack qui vous permet de modifier si quelque chose est consigné lors de l’exécution.

Dans votre code, remplacez NSLog par DDLogVerbose ou DDLogError etc., ajoutez un #import pour les définitions de macro, etc. et configurez les enregistreurs, souvent dans la méthode applicationDidFinishLaunching.

Pour avoir le même effet que NSLog, le code de configuration est

 [DDLog addLogger:[DDASLLogger sharedInstance]]; [DDLog addLogger:[DDTTYLogger sharedInstance]]; 

Du sharepoint vue de la sécurité, cela dépend de ce qui est enregistré. Si NSLog (ou d’autres enregistreurs) écrit des informations sensibles, vous devez alors supprimer le consignateur dans le code de production.

Du sharepoint vue de l’audit, l’auditeur ne souhaite pas examiner chaque utilisation de NSLog pour s’assurer de ne pas enregistrer d’informations sensibles. Il / elle vous dira simplement de retirer l’enregistreur.

Je travaille avec les deux groupes. Nous vérifions le code, rédigeons les guides de codage, etc. Notre guide exige que la journalisation soit désactivée dans le code de production. Les équipes internes savent donc ne pas l’essayer;)

Nous rejetterons également une application externe qui se connecte à la production car nous ne voulons pas accepter le risque associé à une fuite accidentelle d’informations sensibles. Nous nous moquons de ce que le développeur nous dit. Cela ne vaut tout simplement pas notre temps pour enquêter.

Et souvenez-vous, nous définissons «sensible», et non le développeur;)

Je perçois également une application qui effectue beaucoup de consignation en tant qu’application prête à imploser. Il y a une raison pour laquelle la journalisation est effectuée / nécessaire, et généralement pas la stabilité. C’est juste là avec les threads «watchdog» qui redémarrent les services bloqués.

Si vous n’avez jamais passé en revue une architecture de sécurité (SecArch), voici le genre de choses que nous examinons.

Vous ne devriez pas être inutilement verbeux avec printf ou NSLog dans le code de version. Essayez seulement de faire un printf ou un NSLog si l’application a quelque chose de grave, IE une erreur irrécupérable.

Gardez à l’esprit que NSLogs peut ralentir l’interface utilisateur / thread principal. Il est préférable de les supprimer des versions de publication, sauf si cela est absolument nécessaire.

Je recommande fortement d’utiliser TestFlight pour la journalisation (gratuite). Leur méthode écrase NSLog (en utilisant une macro) et vous permet d’activer / désactiver la journalisation sur leur serveur, le journal système Apple et le journal STDERR, pour tous vos appels existants à NSLog. La bonne chose à ce sujet est que vous pouvez toujours examiner vos messages de journal pour les applications déployées sur les testeurs et les applications déployés dans l’App Store, sans que les journaux apparaissent dans le journal système de l’utilisateur. Le meilleur des deux mondes.