Débogage dans iOS - Conseils essentiels

Que vous essayiez de comprendre pourquoi votre tableau contient 3 objets au lieu de 5 ou pourquoi votre jeu est joué à l'envers depuis que le nouveau gars a commencé, le débogage est un élément essentiel du processus de développement. À la fin de cet article, vous comprendrez les principales installations de débogage à votre disposition et vous expliquera comment les utiliser pour réduire vos bogues plus rapidement..

Nous allons couvrir comment:

  • Inspectez l'état de vos applications à l'aide de la console
  • Effectuer la journalisation et aller au-delà de NSLog
  • Suivre l'utilisation de la mémoire en suivant les cycles de vie des objets

Inspection à l'aide de la console

Cette petite boîte noire au bas de Xcode devrait être votre meilleur ami en matière de débogage. Il génère des messages de journal, des messages d'erreur et toutes sortes d'autres choses utiles qui vous aideront à localiser les erreurs. En plus de lire la sortie directement à partir du journal, nous pouvons également nous arrêter à un point donné de notre programme et inspecter différentes parties de notre application..

Rupture conditionnelle

Je vais supposer que vous savez comment fonctionnent les points d'arrêt (et si vous ne le faites pas, ne vous inquiétez pas, vous le détecterez à la fin de la séance!). Les points d'arrêt sont inestimables pour voir où se situe notre application à un moment donné, mais il peut être difficile de parcourir une boucle ou une fonction récursive après avoir déclenché un point d'arrêt jusqu'à ce que notre objet atteigne une certaine valeur. Entrer des points d'arrêt conditionnels!

Les points d'arrêt conditionnels sont des points d'arrêt qui ne seront rompus que lorsqu'une certaine condition est remplie. Imaginons que nous ne voulions casser que lorsqu'un objet est dans un certain état ou lors de la 'nième' itération d'une boucle. Ajoutez un point d'arrêt à votre code en cliquant sur la "gouttière" de l'éditeur Xcode, cliquez avec le bouton droit de la souris sur le point d'arrêt, puis sélectionnez "éditer le point d'arrêt" pour définir des conditions spéciales..

Vous pouvez fournir une condition (par exemple, i == 12) ou le nombre de fois que le point d'arrêt doit être ignoré. Vous pouvez également ajouter des actions qui se produisent automatiquement à la pause, par exemple une commande de débogage imprimant une valeur..

Pointe: Le raccourci clavier pour ajouter / supprimer un point d'arrêt est commande + \

Une autre astuce importante à mettre en œuvre consiste à ajouter le «point d'arrêt d'exception». Jamais remarqué que, dans 99% des cas, lorsque nous rencontrions une exception, Xcode nous entraînait dans le pool de libération automatique dans notre méthode principale.?


Merci Xcode… vraiment utile!

En définissant un point d'arrêt d'exception, vous pouvez accéder à la ligne de code exacte qui a provoqué l'exception avec un point d'arrêt. Pour ce faire, ouvrez l'onglet des points d'arrêt des exceptions (commande + 6). En bas à gauche de la fenêtre, il y a un bouton "+". Sélectionnez cette option pour ajouter un "point d'arrêt d'exception". Maintenant, quand Xcode rencontre une exception, il va casser où dans le code il s'est produit.

Impression manuelle à partir de la console

Si nous avons rompu à un moment donné dans notre application, en général, c'est parce que nous voulons voir l'état de nos objets. Xcode nous fournit la "vue des variables" qui est cette vue au bas de Xcode, à côté de la console. En théorie, il affiche l'état actuel de toutes les valeurs pertinentes dans le contexte actuel. En pratique, cela s'avère parfois être un peu buggy. Parfois, il ne liste pas les valeurs ou ne les met pas à jour lorsque vous parcourez.

Heureusement, nous pouvons inspecter nous-mêmes des objets spécifiques à l’aide de commandes de console très utiles. Taper 'po' dans la console nous permet d’obtenir des détails instantanés sur un objet donné (lorsque nous traitons des valeurs scalaires, nous utilisons 'p').

Cela peut être utile pour voir si un objet existe déjà (cela affichera néant si ce n'est pas le cas), déterminer la valeur d'un objet, déterminer le contenu d'un tableau / dictionnaire au moment de l'exécution et même comparer deux objets. Étant donné que cette commande imprime l'adresse mémoire de l'objet concerné, vous pouvez imprimer deux objets qui devraient être identiques et voir s'ils ont la même adresse mémoire pour vous en assurer..

Une autre commande utile mais cachée que vous pouvez utiliser pour inspecter facilement vos vues est la description récursive commander. Appelez cette option pour obtenir une impression de sa hiérarchie de vues..


Enregistrement efficace

À certains moments, lorsque nous déboguons notre programme, nous voulons enregistrer un certain message sur la console. La fonction 'NSLog' nous permet d'imprimer n'importe quelle sortie que nous voulons sur la console. Cela peut être important si nous voulons suivre certaines voies dans notre application ou tester ce qu’une valeur est égale sans avoir à placer explicitement des points de rupture sur toutes les lignes possibles. NSLog suit le même format que [NSString StringWithFormat] méthode (comme vous pouvez le voir dans le raccourci ci-dessous).

Pointe: Nouveau pour le formatage des chaînes dans Objective-C? Consultez le guide de programmation des chaînes de pommes

Devenir intelligent avec NSLog

Bien que NSLog soit utile, nous devons être intelligents quant à la manière de le mettre en œuvre. Tout ce qui est imprimé à partir de NSLog est enregistré dans le code de production et est donc visible par quiconque. Si quelqu'un devait brancher le périphérique sur l'organiseur et regarder la console, il pouvait voir chaque message du journal. Comme vous pouvez l’imaginer, cela pourrait avoir de graves conséquences! Imaginez si vous imprimiez une logique d'algorithme secret ou le mot de passe de l'utilisateur sur la console! De ce fait, les applications sont parfois rejetées si Apple détecte trop de sortie vers la console dans une version de production..

Heureusement, il existe un meilleur moyen de se connecter. En fonction des efforts que vous souhaitez déployer, il existe plusieurs façons de procéder. Le moyen le plus simple consiste peut-être à utiliser une macro qui inclut uniquement NSLog dans les versions de débogage. Le fait de l'inclure dans un fichier d'en-tête accessible globalement signifie que vous pouvez mettre autant de journaux que vous le souhaitez dans votre code ou qu'aucun d'entre eux ne passera en production (à condition de ne pas modifier les valeurs de macro par défaut du pré-processeur et qu'est-ce que c'est, ne vous inquiétez pas).

 #ifdef DEBUG #define DMLog (…) NSLog (@ "% s% @", __PRETTY_FUNCTION__, [NSString stringWithFormat: __ VA_ARGS__]) #else #define DMLog (…) do  while 0 while (0)

Maintenant, si vous utilisez DMLog (ou ce que vous choisissez d'appeler le vôtre), cela ne sera imprimé que lors d'une construction de débogage. Toute construction de production ne fera rien. __PRETTY_FUNCTION__ aide également en imprimant le nom de la fonction d'où provient l'enregistrement.

Passer à l'étape suivante

Bien que NSLog soit excellent, il comporte un certain nombre de limitations:

  • Il n'imprime que localement
  • Vous ne pouvez pas donner à un journal un "niveau". (Par exemple, critique, avertissement, tout, etc.)
  • NSLog est lent. Cela peut considérablement ralentir votre programme lorsque vous effectuez une grande quantité de traitement

Pour ceux qui veulent s’imprégner de la journalisation, il existe des frameworks qui permettent de surmonter certaines ou toutes ces limitations en fonction des efforts que vous souhaitez déployer. Je vous recommande d’examiner les outils suivants:

  • Cocoa LumberJack - L’un des cadres d’exploitation forestière bien connus et polyvalents de Cocoa. Un peu d'apprentissage mais c'est très puissant
  • SNLog - Un remplacement immédiat pour NSLog

Suivi des cycles de vie d'un objet

Bien que l'introduction du comptage automatique des références (ARC) ait permis de faire en sorte que la gestion de la mémoire ne corresponde plus au temps considérable, il est toujours important de suivre les événements importants du cycle de vie de notre objet. Après tout, ARC n'élimine pas la possibilité de fuites de mémoire ou d'essayer d'accéder à un objet libéré (cela rend simplement la tâche plus difficile). À cette fin, nous pouvons mettre en œuvre un certain nombre de processus et d'outils pour nous aider à garder un œil sur ce que font nos objets..

Enregistrement des événements importants

Les deux méthodes les plus importantes du cycle de vie d’un objet Objective-C sont les suivantes: init et dealloc méthodes. C'est une bonne idée de consigner ces événements sur votre console afin que vous puissiez regarder quand vos objets prennent vie et, plus important encore, vous assurer qu'ils disparaissent lorsqu'ils sont supposés fonctionner..

 - (id) init self = [super init]; if (self) NSLog (@ "% @:% @", NSStringFromSelector (_cmd), self);  retourner soi-même;  - (void) dealloc NSLog (@ "% @:% @", NSStringFromSelector (_cmd), self); 

Taper ce code peut sembler fastidieux au début, mais il existe des moyens d'automatiser le processus et de le rendre plus facile. Je peux vous garantir que cela vous sera utile lorsque votre application se comportera d'une manière qui ne devrait pas l'être. Vous pouvez également utiliser quelques astuces que vous avez apprises dans la section relative à la journalisation afin qu'elles ne soient pas imprimées dans une version de production (ou mieux encore, créez une macro vous-même!).

L'analyseur statique et l'inspecteur

Xcode contient deux outils que nous pouvons utiliser pour nettoyer notre code et le rendre moins sujet aux erreurs. L'outil Static Analyzer est un moyen astucieux pour Xcode de recommander des améliorations de notre code, des objets inutilisés aux objets potentiellement libérés ou sous-libérés (toujours un problème pour les objets ARC for Core Foundation). Pour voir ces recommandations, allez à Produit et sélectionnez 'Anlayze'.

L'inspecteur est un outil puissant qui nous permet d '"inspecter" de manière approfondie divers aspects de notre application relatifs à l'utilisation de la mémoire, à l'activité sur le système de fichiers et fournit même des moyens d'automatiser l'interaction de l'interface utilisateur. Pour "inspecter" votre application, sélectionnez "Profil" dans le menu déroulant "Produit"..

Cela ouvrira la fenêtre Instruments dans laquelle vous pourrez sélectionner un modèle de profil à exécuter. Les plus courants à exécuter sont les zombies (nous en reparlerons plus tard), le moniteur d'activité et les fuites. Leaks est peut-être le modèle le plus utile à utiliser pour rechercher les fuites de mémoire éventuellement présentes dans votre application..

Les zombies sont ton ami

Bien qu'il soit beaucoup plus difficile de rencontrer l'erreur redoutée EXC_BAD_ACCESS maintenant que l'ARC est en place, cela peut toujours se produire dans certaines circonstances. Lorsque vous utilisez des objets UIPopoverController ou Core Foundation, vous pouvez toujours essayer d'accéder à un objet libéré. Normalement, quand on libère un objet en mémoire, il est parti pour toujours. Cependant, lorsque les zombies sont activés, l'objet est uniquement marqué comme libéré mais reste en mémoire. Ainsi, lorsque nous accédons à un objet Zombie, Xcode peut nous indiquer que vous avez essayé d'accéder à un objet qui normalement n'y serait pas. Parce qu'il sait toujours ce que c'est, il peut vous laisser savoir où et quand c'est arrivé.

Vous pouvez chasser les zombies en utilisant deux méthodes. Soit en utilisant l'inspecteur et en exécutant un modèle de profil Zombie, soit en l'activant en tant qu'option de diagnostic dans l'option de construction "Exécuter". Juste à côté du bouton d'arrêt, cliquez sur le nom du schéma, puis sur "Modifier le schéma" et, sous Exécuter, cliquez sur l'onglet Diagnostic et sélectionnez "Activer les objets Zombie". Notez que le débogage en mode Zombie n’est disponible que lors du débogage dans le simulateur, vous ne pouvez pas le faire sur un périphérique réel..


Conclusion

Espérons que ce qui précède vous a donné quelques indications sur la manière de déboguer vos applications plus efficacement. Il s'agit avant tout de trouver des moyens de réduire le temps passé à résoudre les problèmes afin que nous puissions passer plus de temps à faire ce qui est important, à créer de super applications.!

Ce n'est en aucun cas une liste exhaustive. Il existe de nombreuses autres techniques qui n'ont pas été abordées ici, telles que les problèmes de débogage en production, les rapports de bogues à distance, les rapports d'incidents, etc. Avez-vous une technique que vous souhaitez partager? Peut-être avez-vous une question concernant l'un des points ci-dessus? Postez-le ci-dessous dans les commentaires!

Bonne programmation!