Debugging with Breakpoints
TrailLog's stats screen says the hiker has walked 3 km in total, yet the journal holds hikes of 8.5, 14 and 3 km. You could scatter print calls and rebuild again and again. Or you can stop the app on the exact line, look at every value, and walk forward one line at a time.
The rule
Pause where you doubt, inspect what you assumed, step until it surprises you.
Breakpoints. Click a line number in the source editor gutter and a blue marker appears. When the running app reaches that line, it pauses before running it. Click the marker again to disable it (it turns pale); drag it out of the gutter to delete it. ⌘\ toggles a breakpoint on the current line.
Right-click a breakpoint to edit it: add a condition (hikes.count > 2) so it pauses only when that is true, or an action that logs a message and continues automatically — a print statement without rebuilding.
While paused, the debug area shows:
- the variables view — every local value and property, expandable;
- the console, where you can type LLDB commands such as
po totalto print a value.
The Debug navigator (left) shows the call stack: which function called which to reach this line, per thread, plus CPU and memory gauges. Click a frame to see its code and variables.
Stepping controls sit at the top of the debug area:
- Continue — run until the next breakpoint.
- Step Over — run the current line, including any functions it calls, then pause on the next line.
- Step Into — if the line calls your function, go inside it.
- Step Out — finish the current function and pause back in its caller.
func totalDistance(of hikes: [Hike]) -> Double {
var total = 0.0
for hike in hikes {
total = hike.distanceKm // the bug: should be +=
}
return total
}The shortcut
Write down what you expect a value to be, then break just before it changes. The first line where reality differs from your note is where the bug is.
Expect
Three hikes, 8.5 + 14 + 3, so
totalshould grow: 8.5, 22.5, 25.5.
The trap is Step Into on a line that calls Apple's framework code, landing in assembly. Use Step Over for lines that call code you did not write.
Drills
Answer fast — trust the rule.
When a breakpoint on a line is hit, has that line run yet?
You are paused on let total = totalDistance(of: hikes) and want to see inside totalDistance. Which control?
A bug only appears on the 50th hike in a loop. What saves the most time?
Where do you see which function called the one you are paused in?
Remember
- Pause where you doubt, inspect what you assumed, step until it surprises you.
- Step Over runs a line; Step Into enters a call; Step Out returns to the caller.
- Conditions and log actions make breakpoints better than
printand rebuild.
