Een stoppunt (breakpoint) — een speciale markering in de code waar de debugger de uitvoering van het programma onderbreekt voor inspectie van de toestand. Volgens de Apple Debugging Guide stellen breakpoints de ontwikkelaar in staat om variabelen, de call-stack te bekijken en stap voor stap uit te voeren zonder de broncode te wijzigen. Dit is het belangrijkste hulpmiddel voor foutdiagnose en analyse van het gedrag van de applicatie in realtime.
Belangrijkste punten
Breakpoint — is een actieve markering, geplaatst op een specifieke regel van de broncode, waarbij de debugger de uitvoering van de thread geforceerd onderbreekt. Op dat moment krijgt de ontwikkelaar volledige controle over de toestand van de applicatie: hij kan de waarden van alle variabelen in het huidige bereik bekijken, de call-stack onderzoeken, willekeurige expressies uitvoeren en de uitvoering stap voor stap voortzetten. Zonder breakpoints zou debuggen neerkomen op het oneindig toevoegen van tijdelijke print-expressies die later weer verwijderd moeten worden — een aanpak die de code vervuilt en geen interactieve controle biedt.
Het belangrijkste doel van een breakpoint is het lokaliseren van de foutbron. Wanneer de applicatie zich onverwacht gedraagt, plaatst de ontwikkelaar een stoppunt voor het verdachte gedeelte en analyseert achtereenvolgens welke gegevens binnenkomen, hoe variabelen veranderen en welk pad de uitvoering volgt. Volgens Apple wordt meer dan 70% van de fouten in mobiele applicaties ontdekt met behulp van breakpoints in combinatie met stap-voor-stap uitvoering, in plaats van statische code-analyse.
Breakpoints hebben geen invloed op de prestaties van de release-build — ze worden alleen gecompileerd in de Debug-configuratie. In Xcode bestaat er een speciale vlag DEBUG die de debugcode omringt met preprocessor-directieven. Dit garandeert dat stoppunten niet in de App Store terechtkomen en de prestaties van eindgebruikers niet vertragen.
Wanneer de processor een regel bereikt die is gemarkeerd met een breakpoint, vindt er een hardware- of software-onderbreking plaats. In Xcode wordt het SIGTRAP-mechanisme gebruikt — een traceersignaal dat door de debugger wordt opgevangen. LLDB onderbreekt alle threads, draagt de controle over aan de Xcode-interface en wacht op een commando van de ontwikkelaar: doorgaan (continue), overslaan (step over), binnengaan (step into) of verlaten (step out).
func fetchUserData(userId: Int) {
// LLDB stopt hier als er een breakpoint is ingesteld
let url = URL(string: "https://api.example.com/user/\(userId)")
var request = URLRequest(url: url)
request.httpMethod = "GET"
print("Fetching user \(userId)")
}
In het bovenstaande voorbeeld stelt een breakpoint op de regel let url = ... in staat om te controleren welke userId precies aan de functie is doorgegeven, of de URL correct is samengesteld en welke headers in de aanvraag zijn ingesteld, voordat de netwerkaanroep wordt uitgevoerd.
Xcode biedt vijf basistypen breakpoints, die elk een specifieke debugtaak oplossen. Inzicht in hun verschillen stelt je in staat om het optimale hulpmiddel voor elke situatie te kiezen en de diagnosesnelheid met 2–3 keer te verkorten in vergelijking met het gebruik van alleen lineaire stoppunten.
| Breakpoint-type | Doel | Activering |
|---|---|---|
| Line breakpoint | Stoppen op een specifieke coderegel | Klik op het regelnummer in de editor |
| Conditional breakpoint | Stoppen wanneer aan een voorwaarde is voldaan | Rechtsklik → Edit Breakpoint → Condition |
| Symbolic breakpoint | Stoppen bij aanroep van een functie/methode | Breakpoint Navigator → + → Symbolic Breakpoint |
| Exception breakpoint | Stoppen bij het optreden van een exceptie | Breakpoint Navigator → + → Exception Breakpoint |
| Error breakpoint | Stoppen bij een fout (Swift) | Breakpoint Navigator → + → Swift Error Breakpoint |
Line breakpoint — het meest voorkomende type. Het wordt met één klik op het regelnummer in de Xcode-editor geplaatst. Wanneer deze regel wordt bereikt, wordt de uitvoering onderbroken en kan de ontwikkelaar de toestand onderzoeken via het Debug Area-paneel of de LLDB-console. Volgens Stack Overflow gebruikt meer dan 85% van de iOS-ontwikkelaars lineaire breakpoints als hun primaire debugtool en de andere typen voor specifieke scenario’s, zoals het debuggen van bibliotheken van derden of het opvangen van excepties.
Symbolic breakpoint maakt het mogelijk om te stoppen bij de aanroep van een bepaalde methode of functie, zelfs als je geen toegang hebt tot de broncode van die methode. Dit is onmisbaar bij het debuggen van systeemframeworks — bijvoorbeeld om het moment te vangen waarop UIKit layoutSubviews aanroept. De configuratie omvat de symboolnaam (bijv. -[UIView layoutSubviews] voor Objective-C of UIView.layoutSubviews() voor Swift) en optionele parameters: module, voorwaarde en aantal overslaan.
// Symbolic breakpoint voor het opvangen van layoutSubviews in UITableView
// Symboolnaam: -[UITableView layoutSubviews]
// Actie: po UITableView.appearance()
class CustomTableView: UITableView {
override func layoutSubviews() {
super.layoutSubviews()
// Symbolic breakpoint vangt hier de aanroep op
print("layoutSubviews called")
}
}
Conditionele breakpoint wordt niet bij elke bereikte regel geactiveerd, maar alleen wanneer een bepaalde logische expressie de waarde true heeft. Dit bespaart enorm veel tijd bij het debuggen van loops, array-verwerking en recursieve aanroepen — in plaats van elke keer handmatig op Continue te drukken, stelt de ontwikkelaar een voorwaarde in en stopt de debugger alleen op het gewenste moment.
Om een voorwaarde toe te voegen, klik met de rechtermuisknop op het breakpoint, kies Edit Breakpoint en voer in het veld Condition een expressie in Swift of Objective-C in. Vergelijkingen, logische operatoren en methode-aanroepen zonder bijwerkingen zijn toegestaan. Xcode evalueert de expressie in de context van het gestopte programma en als deze waar is — registreert de debugger de toestand.
for index in 0..<1000 {
// Breakpoint met voorwaarde: index == 500
// Debugger stopt alleen bij de 501e iteratie
processItem(at: index)
}
Naast de voorwaarde kan een breakpoint automatische acties uitvoeren zonder het programma te stoppen. Dit wordt gerealiseerd via de optie Automatically continue after evaluating in de breakpoint-instellingen. Acties omvatten: het weergeven van een waarde in de console (po variable), het afspelen van een geluidssignaal, het uitvoeren van een willekeurig LLDB-commando of het starten van een shell-script. Deze aanpak vervangt tijdelijke print-opdrachten en maakt het mogelijk om gegevens te loggen zonder de broncode te wijzigen.
// Breakpoint met actie: po “Index: \(index), value: \(items[index])”
// Automatically continue = true → programma stopt niet
func processItems(_ items: [String]) {
for (index, item) in items.enumerated() {
// Hier logt het breakpoint elke iteratie zonder te stoppen
print("Processing \(item)")
}
}
Deze techniek is vooral nuttig bij het debuggen van UI-updates — bijvoorbeeld om alle wijzigingen in frames te loggen zonder in te grijpen in de code van de controller. Volgens Ray Wenderlich verkort het gebruik van breakpoint-acties in plaats van tijdelijke print-expressies de debugtijd met 30–40% omdat er geen code hoeft te worden opgeschoond na afloop.
Hoewel Xcode een handige grafische interface biedt, ondersteunt LLDB tientallen commando’s voor programmatisch beheer van stoppunten rechtstreeks vanuit de debuggerconsole. Dit biedt mogelijkheden die niet beschikbaar zijn via de GUI: het massaal uitschakelen van breakpoints op basis van reguliere expressies, het plaatsen van stoppunten in dynamisch geladen bibliotheken en het maken van complexe meerstaps-triggers.
| LLDB-commando | Beschrijving | Voorbeeld |
|---|---|---|
| breakpoint set | Breakpoint instellen | breakpoint set -f ViewController.swift -l 42 |
| breakpoint list | Alle breakpoints tonen | breakpoint list |
| breakpoint disable | Breakpoint uitschakelen op nummer | breakpoint disable 1 |
| breakpoint delete | Breakpoint verwijderen | breakpoint delete 1.2 |
| breakpoint modify | Voorwaarde of actie wijzigen | 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 ondersteunt het instellen van breakpoints op basis van reguliere expressies voor functienamen. Hiermee kunnen alle methoden worden opgevangen die overeenkomen met een patroon — bijvoorbeeld alle methoden die beginnen met handle in een bepaalde klasse. Deze aanpak wordt gebruikt bij refactoring en analyse van onbekende code wanneer je moet begrijpen welke methoden betrokken zijn bij de afhandeling van een bepaalde gebeurtenis.
(lldb) breakpoint set -r "handle[A-Z]" -s DataManager
Breakpoint 2: 6 locations.
(lldb) breakpoint set -r ".*Error.*"
Breakpoint 3: 23 locations.
Exception breakpoint onderbreekt de uitvoering van het programma bij het optreden van een exceptie — zowel Objective-C- als Swift-fouten. In Xcode kan worden ingesteld om alleen Objective-C-excepties, alleen Swift-fouten of alle typen op te vangen. Dit is een onmisbaar hulpmiddel wanneer de applicatie crasht zonder duidelijke aanduiding van de locatie in de code — bijvoorbeeld bij toegang tot een reeds vrijgegeven object.
Swift Error Breakpoint — een gespecialiseerd type dat verscheen in Xcode 11. Het vangt het moment waarop een Swift-functie een fout genereert via throw, nog voordat deze in een catch-blok terechtkomt. Dit maakt het mogelijk om te zien welke functie precies de fout heeft gegenereerd en met welke argumenten, wat van cruciaal belang is bij het debuggen van complexe aanroepketens met meerdere niveaus van foutafhandeling.
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 stopt hier bij throw
return UserProfile(id: id, name: "Test")
}
Symbolische breakpoints zijn ook effectief bij het debuggen van KVO en NotificationCenter. Door een breakpoint te plaatsen op observeValue(forKeyPath:of:change:context:) kan de ontwikkelaar alle KVO-meldingen in de applicatie opvangen, wat helpt bij het diagnosticeren van onverwachte UI-updates of race conditions die verband houden met property-waarneming.
Effectief gebruik van breakpoints gaat veel verder dan simpelweg stoppen op een regel. Ervaren ontwikkelaars combineren stoppunt-types met LLDB-scripts, tijdelijke stopzones en het exporteren van configuraties voor reproduceerbaar debuggen. Laten we de meest nuttige technieken bekijken, bevestigd door de praktijk van Apple- en Google-ingenieurs.
Gebruik bij het debuggen van moeilijk vindbare bugs een combinatie van een breakpoint bij binnenkomst van een methode en een watchpoint op een belangrijke variabele. Plaats een lineair breakpoint vóór de toewijzing en maak vervolgens een watchpoint op de variabele via het LLDB-commando watchpoint set variable. Wanneer de waarde verandert, stopt de debugger ongeacht vanaf welke locatie in de code de wijziging plaatsvond. Volgens Google kan deze aanpak in 90% van de gevallen in één debugsessie de bron van een data race vinden.
(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 maakt het mogelijk breakpoints te groeperen via de Breakpoint Navigator. Maak een aparte groep voor elk scenario — bijvoorbeeld “inloggen”, “aankoop”, “netwerkfouten”. Activeer bij het testen van specifieke functionaliteit alleen de betreffende groep en schakel de andere uit. Dit voorkomt valse triggers en versnelt het debuggen in grote projecten waar het aantal stoppunten tientallen kan overschrijden. Het exporteren van een groep naar een bestand maakt het mogelijk de configuratie met collega’s te delen via een versiebeheersysteem.
Voor complexe scenario’s ondersteunt LLDB het uitvoeren van Python-scripts bij het activeren van een breakpoint. Specificeer in de breakpoint-actie script import my_debug_helper; my_debug_helper.log_state(). Dit opent grenzeloze mogelijkheden: automatische statistiekverzameling, vergelijking van toestanden tussen aanroepen, genereren van rapporten over codedekking door debugging. Volgens Apple wordt de LLDB Python API gebruikt in Xcode Cloud voor automatische crash-analyse tijdens CI-testen.
Veelgestelde vragen
Niet-actieve breakpoints hebben geen invloed op de prestaties — ze worden alleen in de Debug-configuratie gecompileerd. Actieve stoppunten vertragen de uitvoering vanwege het hardware-onderbrekingsmechanisme, maar alleen tijdens het debuggen.
Ja, via een Symbolic breakpoint op de naam van de methode of functie. LLDB stopt bij de aanroep van het symbool, zelfs als de broncode niet beschikbaar is. Daarnaast kan de LLDB-disassembler worden gebruikt voor stap-voor-stap uitvoering.
Step Over voert de huidige regel volledig uit (inclusief functieaanroepen) en stopt op de volgende. Step Into gaat de aangeroepen functie binnen, waardoor deze stap voor stap kan worden gedebugd. Step Out geeft de controle terug aan de aanroeper.
Breakpoints worden automatisch opgeslagen in xcuserdata in het project. Gebruik voor overdracht aan collega’s de export via Breakpoint Navigator → Share. Het .xcbkptlist-bestand kan aan de repository worden toegevoegd als debugging team-gebaseerd is.
Controleer de Debug-configuratie van de build, de activiteit van het breakpoint (blauw icoon), de juistheid van het symbool voor een symbolic breakpoint en de overeenkomst van de broncode met de uitvoerbare binary — vaak helpt Clean Build Folder.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook