Un point d'arrêt (breakpoint) est un marqueur spécial dans le code, à l'atteinte duquel le débogueur suspend l'exécution du programme pour inspecter l'état. Selon le Apple Debugging Guide, les breakpoints permettent au développeur de visualiser les valeurs des variables, la pile d'appels et d'exécuter pas à pas sans modifier le code source. C'est l'outil principal pour diagnostiquer les erreurs et analyser le comportement de l'application en temps réel.
Points clés
Un breakpoint est un marqueur actif placé sur une ligne spécifique du code source, à l'atteinte duquel le débogueur suspend de force l'exécution du thread. À ce moment, le développeur obtient un contrôle total sur l'état de l'application : il peut visualiser toutes les variables dans la portée actuelle, examiner la pile d'appels, exécuter des expressions arbitraires et continuer l'exécution pas à pas. Sans breakpoints, le débogage se résumerait à ajouter sans fin des expressions print temporaires puis à les supprimer — une approche qui pollue le code et n'offre aucun contrôle interactif.
L'objectif principal d'un breakpoint est de localiser la source d'une erreur. Lorsqu'une application se comporte de manière inattendue, le développeur place un point d'arrêt avant la section suspecte et analyse séquentiellement les données d'entrée, comment les variables changent et par quel chemin l'exécution progresse. Selon Apple, plus de 70 % des bogues dans les applications mobiles sont identifiés précisément à l'aide de breakpoints combinés à une exécution pas à pas, plutôt que par une analyse statique du code.
Les breakpoints n'affectent pas les performances des versions Release — ils ne sont compilés que dans la configuration Debug. Xcode dispose d'un indicateur spécial DEBUG qui encapsule le code de débogage avec des directives de préprocesseur. Cela garantit que les breakpoints ne se retrouvent pas dans l'App Store et ne ralentissent pas les utilisateurs finaux.
Lorsque le processeur atteint une ligne marquée d'un breakpoint, une interruption matérielle ou logicielle se produit. Dans Xcode, le mécanisme SIGTRAP est utilisé — un signal de trace intercepté par le débogueur. LLDB suspend tous les threads, passe le contrôle à l'interface Xcode et attend la commande du développeur : continuer (continue), pas à pas principal (step over), entrer (step into) ou sortir (step out).
func fetchUserData(userId: Int) {
// LLDB will stop here if breakpoint is set
let url = URL(string: "https://api.example.com/user/\(userId)")
var request = URLRequest(url: url)
request.httpMethod = "GET"
print("Fetching user \(userId)")
}
Dans l'exemple ci-dessus, le breakpoint défini sur la ligne let url = ... permet de vérifier quel userId a été passé à la fonction, si l'URL a été correctement assemblée et quels en-têtes sont définis dans la requête avant que l'appel réseau ne soit exécuté.
Xcode propose cinq types principaux de breakpoints, chacun résolvant une tâche de débogage spécifique. Comprendre leurs différences permet de choisir l'outil optimal pour chaque situation et de réduire le temps de diagnostic de 2 à 3 fois par rapport à l'utilisation de seuls points d'arrêt linéaires.
| Type de breakpoint | Objectif | Activation |
|---|---|---|
| Line breakpoint | Arrêt sur une ligne de code spécifique | Clic sur le numéro de ligne dans l'éditeur |
| Conditional breakpoint | Arrêt lorsqu'une condition est remplie | Clic droit → Edit Breakpoint → Condition |
| Symbolic breakpoint | Arrêt lors de l'appel d'une fonction/méthode | Breakpoint Navigator → + → Symbolic Breakpoint |
| Exception breakpoint | Arrêt lors du lancement d'une exception | Breakpoint Navigator → + → Exception Breakpoint |
| Error breakpoint | Arrêt lors d'une erreur (Swift) | Breakpoint Navigator → + → Swift Error Breakpoint |
Le Line breakpoint est le type le plus courant. Il se définit d'un simple clic sur le numéro de ligne dans l'éditeur Xcode. Lorsque cette ligne est atteinte, l'exécution est suspendue et le développeur peut inspecter l'état via le panneau Debug Area ou la console LLDB. Selon les statistiques de Stack Overflow, plus de 85 % des développeurs iOS utilisent les breakpoints linéaires comme outil de débogage principal, tandis que les autres types sont utilisés pour des scénarios spécifiques comme le débogage de bibliothèques tierces ou l'interception d'exceptions.
Un Symbolic breakpoint permet de s'arrêter lors de l'appel d'une méthode ou fonction spécifique, même sans accès au code source de cette méthode. C'est indispensable lors du débogage de frameworks système — par exemple, pour intercepter le moment où UIKit appelle layoutSubviews. La configuration inclut le nom du symbole (ex. -[UIView layoutSubviews] pour Objective-C ou UIView.layoutSubviews() pour Swift) et des paramètres optionnels : module, condition et nombre d'ignorés.
// Symbolic breakpoint to intercept layoutSubviews on UITableView
// Symbol name: -[UITableView layoutSubviews]
// Action: po UITableView.appearance()
class CustomTableView: UITableView {
override func layoutSubviews() {
super.layoutSubviews()
// Symbolic breakpoint here will intercept the call
print("layoutSubviews called")
}
}
Un breakpoint conditionnel ne se déclenche pas à chaque exécution de la ligne, mais uniquement lorsqu'une expression logique spécifiée est évaluée à true. Cela fait gagner un temps considérable lors du débogage de boucles, de traitements de tableaux et d'appels récursifs — au lieu de cliquer manuellement sur Continue à chaque fois, le développeur définit une condition et le débogueur ne s'arrête qu'au moment pertinent.
Pour ajouter une condition, faites un clic droit sur le breakpoint, sélectionnez Edit Breakpoint et saisissez une expression en Swift ou Objective-C dans le champ Condition. Les comparaisons, les opérateurs logiques et les appels de méthode sans effets secondaires sont autorisés. Xcode évalue l'expression dans le contexte du programme arrêté, et si elle est vraie, le débogueur capture l'état.
for index in 0..<1000 {
// Breakpoint with condition: index == 500
// The debugger will stop only on the 501st iteration
processItem(at: index)
}
En plus d'une condition, un breakpoint peut exécuter des actions automatiques sans arrêter le programme. Cela est implémenté via l'option Automatically continue after evaluating dans les paramètres du breakpoint. Les actions incluent : afficher des valeurs dans la console (po variable), émettre un signal sonore, exécuter une commande LLDB arbitraire ou lancer un script shell. Cette approche remplace les expressions print temporaires et permet de journaliser des données sans modifier le code source.
// Breakpoint with action: po «Index: \(index), value: \(items[index])»
// Automatically continue = true → program does not stop
func processItems(_ items: [String]) {
for (index, item) in items.enumerated() {
// Here the breakpoint logs every iteration without stopping
print("Processing \(item)")
}
}
Cette technique est particulièrement utile lors du débogage de mises à jour de l'interface — par exemple, pour journaliser tous les changements de frame sans interférer avec le code du contrôleur. Selon Ray Wenderlich, l'utilisation d'actions de breakpoint au lieu d'expressions print temporaires réduit le temps de débogage de 30 à 40 % grâce à l'absence de nettoyage du code après coup.
Bien que Xcode fournisse une interface graphique pratique, LLDB prend en charge des dizaines de commandes pour la gestion programmatique des points d'arrêt directement depuis la console du débogueur. Cela offre des capacités non disponibles via l'interface graphique : désactivation massive de breakpoints par expression régulière, définition de points d'arrêt dans des bibliothèques chargées dynamiquement et création de déclencheurs complexes en plusieurs étapes.
| Commande LLDB | Description | Exemple |
|---|---|---|
| breakpoint set | Définir un breakpoint | breakpoint set -f ViewController.swift -l 42 |
| breakpoint list | Afficher tous les breakpoints | breakpoint list |
| breakpoint disable | Désactiver un breakpoint par numéro | breakpoint disable 1 |
| breakpoint delete | Supprimer un breakpoint | breakpoint delete 1.2 |
| breakpoint modify | Modifier la condition ou l'action | breakpoint modify -c «i > 100» 1 |
(lldb) breakpoint set -f LoginViewController.swift -l 15 -c "email.isEmpty"
Breakpoint 1: 15 locations added.
(lldb) breakpoint modify 1 -C "po email" -G true
(lldb) breakpoint list
1: name = 'LoginViewController.swift:15', condition = 'email.isEmpty'
1.1: addr = 0x1000a3b40
LLDB prend en charge la définition de breakpoints par expression régulière pour les noms de fonctions. Cela permet d'intercepter toutes les méthodes correspondant à un modèle — par exemple, toutes les méthodes commençant par handle dans une classe spécifique. Cette approche est utilisée lors du refactoring et de l'analyse de code inconnu lorsque vous devez comprendre quelles méthodes sont impliquées dans le traitement d'un événement particulier.
(lldb) breakpoint set -r "handle[A-Z]" -s DataManager
Breakpoint 2: 6 locations.
(lldb) breakpoint set -r ".*Error.*"
Breakpoint 3: 23 locations.
Un Exception breakpoint arrête l'exécution du programme lorsqu'une exception est levée — à la fois les erreurs Objective-C et Swift. Dans Xcode, vous pouvez configurer l'interception uniquement des exceptions Objective-C, uniquement des erreurs Swift ou de tous les types. C'est un outil indispensable lorsque l'application plante sans indication claire de l'emplacement dans le code — par exemple, lors de l'accès à un objet désalloué.
Le Swift Error Breakpoint est un type spécialisé introduit dans Xcode 11. Il intercepte le moment où une fonction Swift lance une erreur via throw, avant qu'elle n'atteigne un bloc catch. Cela permet de voir quelle fonction a généré l'erreur et avec quels arguments, ce qui est crucial lors du débogage de chaînes d'appels complexes avec plusieurs niveaux de gestion d'erreurs.
enum NetworkError: Error {
case invalidURL
case noData
case decodingFailed(String)
}
func loadUserProfile(id: Int) throws -> UserProfile {
guard id > 0 else {
throw NetworkError.invalidURL
}
// Swift Error Breakpoint will stop here on throw
return UserProfile(id: id, name: "Test")
}
Les breakpoints symboliques sont également efficaces lors du débogage de KVO et NotificationCenter. En définissant un breakpoint sur observeValue(forKeyPath:of:change:context:), le développeur peut intercepter toutes les notifications KVO dans l'application, ce qui aide à diagnostiquer des mises à jour inattendues de l'interface ou des conditions de course liées à l'observation de propriétés.
L'utilisation efficace des breakpoints va bien au-delà du simple arrêt sur une ligne. Les développeurs expérimentés combinent les types de points d'arrêt avec des scripts LLDB, des zones d'arrêt temporaires et l'export de configuration pour un débogage reproductible. Examinons les techniques les plus utiles, appuyées par la pratique des ingénieurs d'Apple et de Google.
Lors du débogage de bogues difficiles à attraper, utilisez une combinaison d'un breakpoint à l'entrée de la méthode et d'un watchpoint sur le changement d'une variable clé. Définissez un breakpoint linéaire avant l'affectation, puis créez un watchpoint sur la variable via la commande LLDB watchpoint set variable. Lorsque la valeur change, le débogueur s'arrêtera indépendamment de l'endroit du code où la modification a eu lieu. Selon Google, cette approche permet de trouver la source d'une condition de course dans 90 % des cas en une seule session de débogage.
(lldb) watchpoint set variable self->_balance
Watchpoint 1: addr = 0x600000c4b80 size = 8
state = enabled type = w
watchpoint spec: 'self._balance'
(lldb) watchpoint list
1: location = 0x600000c4b80, type = write, variable = '_balance'
Xcode permet de regrouper les breakpoints via le Breakpoint Navigator. Créez un groupe séparé pour chaque scénario — par exemple, «connexion», «achat», «erres réseau». Lors du test d'une fonctionnalité spécifique, activez uniquement le groupe correspondant, en désactivant les autres. Cela évite les déclenchements intempestifs et accélère le débogage dans les grands projets où le nombre de breakpoints peut dépasser plusieurs dizaines. L'export d'un groupe dans un fichier permet de partager la configuration avec des collègues via le contrôle de version.
Pour les scénarios complexes, LLDB prend en charge l'exécution de scripts Python lors du déclenchement d'un breakpoint. Dans l'action du breakpoint, spécifiez script import my_debug_helper; my_debug_helper.log_state(). Cela ouvre des possibilités illimitées : collecte automatique de statistiques, comparaison d'états entre appels, génération de rapports de couverture de débogage. Selon Apple, l'API Python de LLDB est utilisée dans Xcode Cloud pour l'analyse automatique des crashs lors des tests CI.
Foire aux questions
Les breakpoints inactifs n'affectent pas les performances — ils ne sont compilés qu'en configuration Debug. Les points actifs ralentissent l'exécution en raison du mécanisme d'interruption matérielle, mais uniquement pendant le débogage.
Oui, via un Symbolic breakpoint par nom de méthode ou de fonction. LLDB s'arrêtera lors de l'appel du symbole, même si le code source n'est pas disponible. De plus, vous pouvez utiliser le désassembleur LLDB pour une navigation pas à pas.
Step Over exécute la ligne actuelle entièrement (y compris les appels de fonction) et s'arrête à la ligne suivante. Step Into entre dans la fonction appelée, permettant de la déboguer pas à pas. Step Out redonne le contrôle à l'appelant.
Les breakpoints sont automatiquement sauvegardés dans xcuserdata dans le projet. Pour partager avec des collègues, utilisez l'export via Breakpoint Navigator → Share. Le fichier .xcbkptlist peut être ajouté au dépôt si le débogage est collaboratif.
Vérifiez la configuration Debug de la compilation, l'activité du breakpoint (icône bleue), l'exactitude du symbole pour les breakpoints symboliques et la correspondance du code source avec le binaire exécutable — un Clean Build Folder aide souvent.
Résumé
Nous développerons une application mobile clé en main
IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.
Lisez aussi