Bienvenue dans la sixième partie de la série Mobiletuts + Beginning iOS Development. Cet acompte couvrira les bases du débogage Xcode. Il inclura un bref aperçu de la théorie du débogage logiciel et une application pratique pour démontrer l'utilisation des points d'arrêt et du débogueur Xcode. L'article se terminera par quelques conseils généraux et meilleures pratiques, ainsi qu'une liste de ressources utiles à votre disposition pour poursuivre votre apprentissage..
Des problèmes pour visualiser les médias ci-dessus? Accédez à la version complète de haute qualité de cette vidéo dans son format original, MOV.
Au lieu de créer une nouvelle application spécialement pour ce tutoriel, j'ai repris l'application FortuneCrunch que nous avons créée dans la deuxième partie de cette série et j'ai introduit un certain nombre d'erreurs différentes dans le code source.. Téléchargez BrokenCrunch, la version brisée de FortuneCrunch qui accompagne ce message., suivre pendant que je montre comment utiliser les outils de débogage Xcode.
Avant de commencer à déboguer BrokenCrunch, parlons un peu de la théorie du débogage logiciel. En général, les erreurs logicielles (également appelées "bugs") peuvent être classées comme suit:
Comme son nom l'indique, une erreur de compilation se produit lorsque vous essayez de compiler le code source de votre application. Dans Xcode, cela se produit lorsque vous sélectionnez "Build and Run" ou "Build and Debug" afin de lancer votre application sur le périphérique ou le simulateur. Lorsqu'une erreur de compilation est rencontrée, cela empêchera littéralement le lancement de votre application. Comme nous le verrons, les erreurs de cette catégorie peuvent provenir d'instructions de syntaxe non sensuelles ou incorrectes, ou de problèmes survenant au cours de la phase de liaison de la construction de votre application. En règle générale, les erreurs au moment de la compilation sont les plus faciles à résoudre, car le compilateur envoie généralement un message d'erreur significatif ou un message d'avertissement qui vous alertera de la nature du problème..
Les erreurs d'exécution se produisent après que votre application a été compilée et lancée dans le simulateur ou sur un périphérique. Une panne d'application ou une fuite de mémoire résultant d'une gestion médiocre de la mémoire d'un objet est un exemple d'erreur d'exécution.
Une erreur logique se produit pendant la phase d'exécution d'une application et entraîne un comportement inattendu ou non souhaité de l'application qui entre en conflit avec le résultat souhaité par le développeur du logiciel ou l'intervenant du projet. Un bon exemple d'erreur logique est une formule mathématique mal implémentée. Considérons le théorème de Pythagore:
Si un développeur de logiciel a involontairement implémenté cette formule en tant que:
Le résultat serait une erreur logique, mais cela ne provoquerait probablement pas le blocage de l'application. C’est ce qui rend les erreurs logiques si dangereuses: l’application peut apparemment fonctionner «sans bug» pour le développeur tout en produisant une sortie non valide ou indésirable..
Avec ces connaissances théoriques en place, ouvrez BrokenCrunch et commençons. Après avoir chargé notre exemple d'application, sélectionnez Construire> Construire et déboguer. Vous remarquerez que l'application ne parvient pas à démarrer et que le compilateur a généré un certain nombre d'erreurs. Pour afficher les résultats de la tentative de compilation, sélectionnez Construire> Construire des résultats.
La sélection des erreurs répertoriées vous mènera directement à la ligne de code où l'erreur est signalée. Il est toutefois important de garder à l'esprit que le nombre d'erreurs signalées par le compilateur et les numéros de ligne de ces erreurs doivent être considérés comme la "meilleure estimation" de ce qui ne va pas dans votre application, et non comme une déclaration concluante..
En fait, une simple erreur de syntaxe peut avoir pour conséquence que le compilateur rapporte plusieurs erreurs apparemment sans rapport avec le problème. Par exemple, jetez un oeil à la "Crochet attendu avant 'setImage'" ligne d'erreur. Si vous examinez la ligne en question, vous devriez constater que la syntaxe est parfaite. Il se trouve que le problème ne se trouve pas sur la ligne signalée, mais sur la ligne juste au-dessus. Voyez-vous le problème?
le NSLog ()
déclaration n'a pas été terminée par un point-virgule. Cela signifie que le compilateur ne sait pas que vous avez l'intention de terminer la ligne après la dernière parenthèse et affiche tout ce qui se trouve sur NSLog
à la parenthèse finale de fermeture et le point-virgule après UIControlStateNormal
comme une déclaration.
Ajoutez le point-virgule pour compléter le NSLog
déclaration:
NSLog (@ "In crunchCookie");
Enregistrez le fichier source et cliquez à nouveau sur "Build and Debug". Deux des trois erreurs affichées à l'origine devraient maintenant être résolues.
Ensuite, sélectionnez le "Pas de déclaration de propriété" Erreur. Comme vous pouvez le constater, cette erreur indique que la propriété que nous essayons de synthétiser n'existe pas. Pour vérifier cela, ouvrez le fichier FortuneCrunchViewController.h où la propriété aurait dû être déclarée. Si vous examinez la ligne 17, la syntaxe est correcte, mais nous avons un décalage entre la propriété que nous avons déclarée et celle que nous essayons de synthétiser. Objective-C est un langage sensible à la casse, ce qui signifie que le "C" dans le cookie doit être mis en majuscule pour correspondre à la propriété que nous essayons de synthétiser. Mettez à jour la déclaration de propriété dans le fichier d'en-tête pour lire:
@property (nonatomic, keep) IBOutlet * fortuneCookieButton;
Enregistrez le fichier source et générez et corrigez à nouveau. Cette fois, plutôt que d’ouvrir la construction résulte de Construire> Construire et déboguer, cliquez simplement sur l'icône d'erreur dans le coin inférieur droit de Xcode.
Un pas en avant, quatre pas en arrière. L'erreur concernant la ligne de propriété synthétiser a disparu, mais nous avons une liste entièrement nouvelle d'erreurs. Qu'est-il arrivé?
C'est un bon moment pour noter les différentes phases affichées dans la fenêtre Résultats de la construction:
Notez que nous avons un avertissement sous la section «Compiler» de la sortie des résultats de la construction. C’est la même section dans laquelle nos erreurs précédentes étaient signalées. Maintenant que les trois erreurs précédentes ont été résolues, nous avons pu passer de la phase de compilation à la phase de liaison de notre génération d’application, et toutes les nouvelles erreurs sont erreurs de liaison. Lorsque vous rencontrez une erreur de liaison, c'est généralement parce que vous essayez d'utiliser des fonctions d'un framework que vous n'avez pas réellement inclus dans votre application. Dans ce cas, les résultats de la construction font référence à une fonction appelée _UIApplicationMain
dans le fichier main.o. Main.o est la version compilée, en code machine, de main.m. Jetons un coup d'oeil au code source dans ce fichier. Sur la ligne 13, vous pouvez voir un appel de fonction à UIApplicationMain
:
int retVal = UIApplicationMain (argc, argv, nil, nil);
UIApplicationMain
est une fonction centrale pour chaque application iOS, mais comment pouvez-vous en savoir plus à son sujet et déterminer le cadre dans lequel elle est incluse? Heureusement, le SDK iOS est fourni avec une excellente documentation. Si vous maintenez le bouton d'option (ou alt) enfoncé et que vous double-cliquez sur le nom de la fonction, vous lancerez un résumé de la documentation officielle du SDK iOS traitant de cette fonction. Cliquez sur l'icône «livre» en haut à droite pour afficher la documentation complète disponible. Vous pouvez voir que cela a lancé la documentation de référence de fonction pour la structure UIKit. Bingo, nous avons notre cadre manquant. Cependant, avant d’ajouter le cadre au projet, examinons une autre méthode que vous auriez pu utiliser pour déterminer l’origine de UIApplicationMain
.
Fermez la fenêtre de documentation. Maintenant, maintenez le bouton de commande et double-cliquez sur le UIApplicationMain
une fonction. Vous regardez maintenant la source de UIApplication.h, le fichier de déclaration d’en-tête qui contient le fichier UIApplicationMain
déclaration de fonction. Si vous faites défiler vers le haut de la fenêtre, vous verrez que ce fichier importe plusieurs autres en-têtes UIKit et que le commentaire en haut inclut le nom du cadre «UIKit»..
Passons maintenant à la résolution de ces erreurs de liaison en incluant le framework UIKit. Pour ce faire, cliquez avec le bouton droit de la souris ou cliquez avec le bouton droit de la souris sur le dossier Frameworks dans le volet Groupes et fichiers, puis sélectionnez ajouter> cadres existants. Trouvez le framework UIKit et cliquez sur «Ajouter». Pour tester notre travail, sélectionnez à nouveau Build and Debug.
Comme vous pouvez le constater, le simulateur a été lancé avec succès et nous sommes en mesure de visualiser notre application. Cela signifie que nous avons résolu toutes les erreurs de compilation de notre application..
Allez-y et cliquez sur le cookie de fortune… comme vous pouvez le constater, cliquer sur le cookie entraîne une erreur d'exécution et l'application s'est écrasée. Le message affiché en bas à gauche de l'écran Xcode n'est pas très utile, regardons donc de plus près en ouvrant la console.
La console affiche à la fois une pile d’appels de ce qui se passait dans l’exécution de notre programme au moment du crash, ainsi qu’une explication plus détaillée: "Application de terminaison en raison d'une exception non interceptée… FortuneCrunchViewController cookieCruncher: sélecteur non reconnu envoyé à l'instance." Ce message signifie que notre bouton appelle le mauvais sélecteur pour l'événement que nous avons déclenché en cliquant sur le cookie. Puisque l'interface pour FortuneCrunch a été construite dans Interface Builder, ouvrons le fichier XIB d'Interface Builder pour «FortuneCrunchViewController» pour examiner de plus près.
Sélectionnez le bouton de cookie et cliquez avec le bouton droit de la souris ou avec le bouton droit de la souris pour afficher une liste des actions connectées:
Vous pouvez voir que l'événement Touch Up Inside fait référence à une cible inexistante, indiquée par le texte jaune. Supprimez la cible «cookieCruncher» inexistante et reconnectez touchUpInside au propriétaire du fichier en sélectionnant la cible «crunchCookie» qui apparaît dans la liste déroulante. Enregistrez votre travail dans Interface Builder, revenez à Xcode et relancez l'application..
Cliquez à nouveau sur le cookie de fortune pour générer une erreur d'exécution. Cette fois, le message de la console n’est pas très utile, il affiche simplement "EXC_BAD_ACCESS".
Examinez les résultats de la construction en sélectionnant Construire> Construire des résultats. Avez-vous remarqué l'avertissement plus tôt? Les avertissements du compilateur sont souvent une indication d'une erreur d'exécution potentielle, mais comme la syntaxe de la ligne pour laquelle l'avertissement est émis n'est pas incorrecte, le compilateur est toujours en mesure de générer l'application avec succès. Bien sûr, il arrive parfois qu'un avertissement du compilateur soit un «indicateur faux» et ne provoque pas d'erreur d'exécution, mais dans 95% des cas, si le compilateur a émis un avertissement indiquant que vous faites quelque chose de mal..
Cliquez sur l'avertissement pour accéder à la ligne de votre code source où il s'est produit.
L'avertissement fait référence à des types de pointeurs incompatibles. Voyez-vous le problème? La méthode imageNamed attend un objet NSString, mais cette ligne de code lui fournit une chaîne de style C littérale. Ajoutez le symbole “@” pour en faire une chaîne Objective-C:
[fortuneCookieButton setImage: [UIImage imageNamed: @ "cookie-closed.png"] pourState: UIControlStateNormal];
Enregistrez vos progrès et exécutez à nouveau l'application.
Cette fois, lorsque vous cliquez sur le cookie fortune, vous rencontrez une erreur logique: l'application ne plante pas et le libellé «Happy iPhone Hacking» s'affiche comme prévu, mais l'image d'arrière-plan reste identique au cookie fermé..
Pour résoudre ce problème, jetons un coup d'œil à la fonction responsable de la transition: (IBAction) crunchCookie
. La ligne 19 est responsable de la modification de l'image d'arrière-plan et vous pouvez voir qu'elle définit la nouvelle image d'arrière-plan sur «cookie-closed.png». Si vous examinez le cookie fermé dans le dossier Ressources, vous constaterez qu'il s'agit en fait de la même image que celle affichée lors du premier chargement de l'application. Nous devons changer cette ligne pour passer à «cookie-crunched.png»:
[fortuneCookieButton setImage: [UIImage imageNamed: @ "cookie-crunched.png"] pourState: UIControlStateNormal];
Générez et exécutez à nouveau l'application… et maintenant, en tapotant sur le cookie, l'image d'arrière-plan attendue avec l'étiquette correctement affichée.
Toutes nos félicitations! Vous venez de parcourir le processus de correction des erreurs de compilation, des erreurs d'exécution et des erreurs logiques dans une application. Pendant tout ce temps, nous avons à peine exploité les puissants outils de débogage mis à votre disposition avec Xcode..
Pour continuer notre exploration des outils de débogage plus avancés disponibles, essayons d'étendre l'application FortuneCrunch pour la rendre un peu plus intéressante. Plutôt que d’afficher la chaîne statique «Happy iPhone Hacking!» À chaque fois que le cookie est craqué, construisons un ensemble de plusieurs NSString
valeurs pouvant être affichées.
Revenez à Xcode et ouvrez le fichier FortuneCrunchViewController.h. Ajoutez le membre de données suivant:
NSArray * fortunes;
Ce tableau sera utilisé pour contenir nos chaînes de fortune aléatoires.
Maintenant, ajoutez la signature de méthode suivante:
-(NSString *) generateRandomFortune;
Cette ligne déclarera une nouvelle méthode dans notre classe qui sera utilisée pour sélectionner une fortune au hasard dans notre tableau de fortunes.
Ensuite, passez à FortuneCrunchViewController.m. Comme cette classe sera lancée à partir de notre fichier XIB, nous devons remplacer le initWithCoder
méthode et allouer le tableau que nous avons déclaré dans le fichier .h, en l’initialisant avec de nouvelles fortunes:
-(id) initWithCoder: aDecoder self = [super initWithCoder: aDecoder]; if (self) fortunes = [[[NSArray alloc]] initWithObjects: @ ”Celui qui jette de la terre perd du terrain.”, @ ”Une bouche fermée ne recueille pas de pieds.”, @ ”Au secours! Je suis prisonnier dans une boulangerie! ”, Nil]; retourner soi-même;
Maintenant que nous avons créé un nouveau NSArray
, n'oubliez pas de le libérer dans le dealloc
méthode:
-(vide) dealloc [publication de fortunes];
Passons maintenant au codage du générerRandomFortune
une fonction:
-(NSString *) generateRandomFortune int selected_index = arc4random ()% 3 * 10; return [fortunes objectAtIndex: Choisi_index];
Ces lignes génèrent simplement un nouveau numéro d’index aléatoire que nous utiliserons pour renvoyer la chaîne de fortune correspondante..
Enfin, modifiez le CrunchCookie
méthode pour utiliser une de nos fortunes aléatoires plutôt que le texte statique "Happy iPhone Hacking!":
fortuneLabel.text = [self generateRandomFortune];
Générez et exécutez l'application après avoir enregistré ces modifications. Si vous cliquez sur le cookie, vous allez créer une erreur d'exécution. Pour comprendre pourquoi cela se produit, nous allons utiliser le débogueur Xcode et des points d'arrêt personnalisés..
Un point d'arrêt est un indicateur qui indique à votre application que l'exécution du programme doit «suspendre» lorsque la ligne avec le point d'arrêt est atteinte. L'exécution de votre application en «mode Création et débogage» vous permet d'utiliser des points d'arrêt. Pour définir un point d'arrêt, cliquez simplement dans l'éditeur "Gouttière" sur la ligne sur laquelle vous souhaitez déclencher un point d'arrêt. Pour comprendre ce qui se passe dans notre application, nous allons définir notre point d'arrêt sur le NSLog
juste après que la méthode crunchCookie s’appelle:
Construire et déboguer l'application avec ce nouveau point d'arrêt en place.
Une fois l'application chargée, cliquez sur le cookie. Si vous regardez en bas à gauche de Xcode, vous verrez le message d'état «Arrêté au point d'arrêt 1». Cela signifie que le débogueur a bien arrêté l'exécution du programme au point d'arrêt que vous avez défini. Vous remarquerez également qu'une flèche rouge indique la ligne d'exécution en cours où le débogueur a mis le programme en pause..
Alors, que pouvez-vous faire avec le débogueur? Plus que ce qui peut être couvert dans un seul tutoriel. Cependant, il existe trois actions fondamentales que vous pouvez entreprendre à ce stade: passer à l’autre, entrer et sortir. Toutes ces options sont disponibles dans la barre de menus du débogueur intégré au code..
Si vous appuyez sur le bouton "pas à pas" dans le menu du débogueur en code, vous remarquerez que l'exécution du programme se poursuit à la ligne suivante. “Step over” continuera simplement l'exécution ligne par ligne dans la méthode actuelle, mais il ne suivra pas l'exécution de votre code s'il passe à une autre méthode. Si vous voulez réellement suivre l’exécution du code dans d’autres appels de méthodes de votre code, vous devrez utiliser le bouton «Pas à pas»..
Comme vous pouvez le constater, nous sommes entrés dans le générerRandomFortune
méthode, qui est exactement ce que nous voulons. Cliquez à nouveau sur «Pas à pas» pour voir ce qui se passe quand arc4random ()
est appelé. Ne serait-il pas intéressant de savoir à quoi la variable selected_index a été définie? Heureusement, nous pouvons! L'une des meilleures fonctionnalités de l'utilisation du débogueur est la possibilité de passer simplement la souris sur les variables pour voir rapidement leur valeur..
Clairement, le Choisi_index
la valeur est beaucoup plus grande que la longueur de notre tableau. Contrairement à d'autres langages de programmation, la fonction de randomisation que nous utilisons renverra un entier. Il n'est donc pas nécessaire de convertir un nombre décimal en entier en multipliant la valeur par 10. Mettez à jour la ligne pour lire:
int selected_index = arc4random ()% 3;
Nous avons fini d’apporter des modifications à cette fonction. Vous devez donc utiliser le bouton «Sortir» pour quitter cette sous-fonction et revenir à CrunchCookie
. Notez que même si nous ne l’avons pas vu, le reste de la fonction s’exécute normalement..
Enfin, notez le bouton de point d'arrêt «Activer / Désactiver» et le bouton «Continuer l'exécution» dans la barre de menus du débogueur dans le code. "Continuer l'exécution" permettra simplement à l'exécution du programme de continuer normalement. Vous pouvez penser à cela comme au bouton «Unpause». Allez-y et appuyez maintenant.
Avant de passer à la désactivation des points d'arrêt, il reste un autre problème à résoudre: ce que vous venez de vivre s'appelle le "débogueur en code". Il est très puissant, mais vous disposez également de deux autres modes de débogage: la fenêtre de débogage complète et la perspective du mini-débogueur..
Pour accéder à la fenêtre du débogueur complet, cliquez sur l'icône "débogage" dans la barre de menu du débogueur en code. Cette fenêtre contient beaucoup plus d'informations que le débogueur en code. Sur la gauche, vous avez une trace de pile affichant le contexte d'exécution du programme (vous avez également la possibilité de sélectionner l'un des threads actuellement générés). À droite, vous pouvez voir un affichage rapide des différentes variables actuellement en mémoire. La sélection d'une autre signature de pile d'appels modifiera l'affichage dans le débogueur. Vous pouvez changer la disposition de la fenêtre du débogueur en allant à Exécuter> Affichage du débogueur.
Enfin, le mini-débogueur est une autre perspective de débogage à votre disposition. J'utilise rarement cette perspective, mais elle vous est accessible depuis Exécuter> Mini-débogueur.
Depuis que nous venons de résoudre l’erreur introduite dans notre code de fortune aléatoire, nous n’avons plus besoin du débogueur. Désactiver les points d'arrêt. Cependant, avant de reconstruire l'application, ajustons la taille de la police de notre étiquette de fortune.
Ouvrez Interface Builder, sélectionnez l'étiquette et modifiez la police de l'inspecteur en Arial Black, 9 points, puis cochez la case «Adapter à l'ajustement» et modifiez la taille de police minimale à 6 points. Maintenant, construisez et exécutez notre projet à nouveau.
Voila! Notre application fonctionne maintenant comme prévu.
Maintenant que vous avez découvert les bases de l’utilisation du débogueur dans Xcode, envisagez d’appliquer les instructions suivantes dans votre flux de travail de développement quotidien:
Bien que le simulateur soit une méthode utile pour tester une application pendant la phase de développement de votre produit, il ne remplace pas les tests sur un périphérique physique. En effet, le simulateur et un périphérique iOS diffèrent de manière importante et fondamentale. Par exemple, le simulateur fonctionne évidemment sous OS X et le système de fichiers sous OS X n'est pas sensible à la casse. Cependant, le système de fichiers sur iOS est sensible à la casse. Donc, se référant au fichier cookie-CRUNChed.png
, au lieu de cookie-crunched.png
, fonctionnera parfaitement dans le simulateur mais échouera sur un périphérique iOS réel. Un autre élément important à prendre en compte est que le simulateur dispose de beaucoup plus de mémoire qu'un dispositif réel, ce qui aura souvent un impact considérable sur l'expérience utilisateur. Enfin, toutes les applications par défaut fournies avec iOS ne sont pas disponibles dans le simulateur, y compris les programmes Maps et App Store. Cela signifie que vous ne pourrez pas tester de code qui génère des itinéraires avec l'application Maps ou des applications de promotion croisée dans l'App Store du simulateur. Ce ne sont que quelques-unes des différences qui existent. Je recommande vivement de tester sur autant d'appareils physiques iOS exécutant autant de versions de iOS ciblées que possible.
Clang Static Analyzer est un outil d'analyse statique spécial C / Objective-C fourni avec Xcode. Cet outil est capable d'analyser votre code pour rechercher des erreurs ou des incohérences qui pourraient sinon passer inaperçues..
Bien que les détails du fonctionnement de l’analyseur débordent du cadre de cet article, son utilisation est heureusement très simple. Pour effectuer une analyse statique de votre code, sélectionnez simplement Construire> Construire et analyser depuis le menu de construction Xcode.
Si vous souhaitez en savoir plus sur le fonctionnement de l'option «Construire et analyser», vous pouvez en savoir plus sur l'analyse de code statique et l'analyseur statique Clang en ligne..
Dans ce didacticiel, nous avons appris le fonctionnement des points d'arrêt en les définissant dans notre code. En plus des points d'arrêt spécifiques à un projet, Xcode vous permettra également de définir des points d'arrêt «globaux» qui s'appliqueront à tous les projets iOS que vous créez dans Xcode. Définition d'un point d'arrêt global sur objc_exception_throw
vous permettra de lancer automatiquement le débogueur chaque fois qu'une exception (un type d'erreur d'exécution) se produit. Pour en savoir plus sur les avantages de cette approche et sur la façon de l'implémenter dans le code, consultez mon conseil rapide iOS sur objc_exception_throw et les points d'arrêt globaux..
Comme mentionné précédemment dans ce didacticiel, la grande majorité des avertissements du compilateur émis doivent être résolus avant le lancement de votre projet et il ne devrait en aucun cas exister de scénario dans lequel du code générant des avertissements du compilateur doit restent inchangés pour qu'une application puisse fonctionner correctement. Par conséquent, certains programmeurs recommandent de traiter tous les avertissements du compilateur comme des erreurs, ce qui les oblige à être résolus dans le cadre du processus de développement normal..
Je soutiens cette idée, sauf quelques cas marginaux, et Xcode facilite son implémentation. Aller à Projet> Modifier les paramètres du projet puis sélectionnez l'onglet Construire. Tapez "Traiter l'avertissement" dans la barre de recherche et vous verrez une valeur booléenne appelée "Traiter les avertissements comme des erreurs". Cochez cette case pour activer la fonctionnalité..
Une autre étape à suivre pour augmenter les chances d'acceptation de votre application la première fois que vous l'envoyez sur iTunes Store consiste à activer l'indicateur «Créer et valider» dans les paramètres de construction du projet. Tapez «valider» dans la zone de recherche de l'onglet de création des paramètres du projet, puis sélectionnez «Valider la création du produit». Cette option exécute certains des tests effectués par les réviseurs Apple, ce qui vous permet d'empêcher potentiellement le rejet de l'App Store. Notez que cocher cette case ne garantit pas que votre application passera en revue l'avis de l'App Store, mais c'est mieux que rien.
Outre la console, les résultats de la construction et le débogueur, il existe quelques autres outils d'optimisation et de débogage intéressants que vous devez connaître dans le cadre de vos efforts de développement. Pour en savoir plus, consultez la documentation des outils suivants:
Cela a été une visite éclair du débogage avec le SDK iOS. Il reste encore beaucoup à faire, mais j'espère que cette leçon a été suffisante pour vous aider à résoudre plus rapidement les bugs dans vos propres applications et à créer de meilleurs logiciels! Si vous souhaitez en savoir plus sur certains des outils avancés décrits dans ce didacticiel, tels que Instruments, Shark ou SpinControl, ou si vous souhaitez en savoir plus sur le débogage en général, laissez un commentaire ci-dessous et laissez-moi savoir.!