Advanced debugging with Xcode đ
When used correctly, debugging tools can help developers save a massive amount of time. Consider, for instance, the most basic breakpoint: it enables us to halt the execution of a program in order to analyze it step-by-step. Now just think how long that process would take if you had to implement it manually, by adding outputs to the console at every line. Things would get quickly out-of-hand and unmanageable.
As it turns out, the standard breakpoints most of us are accustomed to are nothing but the tip of the iceberg, and Xcode has a whole collection of handy tools designed to speed up debugging workflows.
Perform action and do not halt the execution
Letâs start with something most of us have already experienced several times: we set a breakpoint when it is triggered we type a command like po myVariable
, and then we resume the execution.
Of course, this manual operation will become very tedious if we need to perform it more than a few times. Fortunately, itâs quite simple to automate it:
- Right-click on the breakpoint > âEdit BreakpointâŠâ
- Click on âAdd Actionâ
- Select âDebugger Commandâ
- Input your command
- Check âAutomatically continue after evaluating actionsâ
From now on, whenever this breakpoint is triggered, the custom debugger command will be executed and the execution will resume immediately after, thus removing any need for manual actions. Thatâs a lot of time saved đ
Conditional breakpoints
Sometimes we want a breakpoint to be triggered only if a certain condition is met. Once again, using âEdit BreakpointâŠâ, itâs very easy to set such a condition:
In this example, the condition is quite simple, but more complicated expressions can be handled without any trouble, as it is possible to use boolean operators (&&
, ||
, !
, ...) or perform function calls.
Ignore
Conversely, there are times when we want a breakpoint to halt the execution-only from the second time it is triggered. Think, for example, of functions that are called a first time when an object is created, then called again when an event occurs. If we are only interested in debugging the second kind of calls, it would be nice to filter out the first.
Once again, using âEdit BreakpointâŠâ the option is already waiting for us:
Exception breakpoints
When an exception or an error is thrown and is not caught, the application crashes and the callstack gets printed to the console. This output is often very helpful to identify the source of the error, but it does not really allow to inspect the situation that threw the error.
Thatâs when a new kind of breakpoint comes into play. Until now, all the breakpoints we have used were in some way anchored to our code, meaning that they were explicitly set on a specific line of the application.
In order to set a breakpoint that is triggered when an error occurs, we need to look on the side of symbolic breakpoints, meaning breakpoints that are not linked to a particular line, but rather to a well-defined event, in our case the occurrence of an error.
To do so, Xcode already offers two flavors of such breakpoints, depending on whether you are interested in Swift or Objective-C errors:
The great thing is that you can also edit them, in order to make them even more tailored to your need. Just filter for a specific Swift.Error
type, or triggering either when the error is thrown or when it is caught.
Symbolic breakpoints
Exception and error breakpoints are a specific kind of symbolic breakpoints, but itâs also possible to define much more generic ones.
For instance, it is possible to create a breakpoint that will be triggered whenever viewDidLoad()
is called on a controller:
This can be a very helpful tool when you know that a certain method is being called (for instance, a modal controller gets dismissed), and you are trying to pinpoint the source of this call.
Constraint Error Breakpoint
Weâve all been confronted with AutoLayout issues. Generally, we are made aware of these runtime issues through console error messages stating that the auto-layout engine wasâunable to simultaneously satisfy constraintsâ.
However, in complex apps, it can be complicated to understand which view exactly triggered the error. A nice way to pinpoint the root cause is to add a âConstraint Error Breakpointâ to your project.
Then, whenever a new auto-layout issue happens, the breakpoint will be automatically triggered đ
Runtime Issue Breakpoint
New in Xcode 11, a new type of symbolic breakpoint has been introduced. Called âRuntime Issue Breakpointâ, it actually implements checks that previously had to be enabled within the compilation scheme.
Among them, youâll find a âMain Thread Checkerâ that will be fired whenever a UIKit or AppKit object is being accessed from a background thread, or a âThread Sanitizerâ that will help you detect race conditions.
Watchpoint
When you think about it, the breakpoint is a construct that focuses on the code of an application. But an application is made of both code and data, so it could certainly be useful to have the equivalent of a breakpoint, in order to observe how data changes as the application run.
As it happens, such a construct is already available in Xcode, albeit it is not as visible as breakpoints are, and itâs called a watchpoint.
To set a watchpoint on a variable, you first have to set a breakpoint that will halt the execution in a memory frame where the variable is reachable. Then you just need to right-click the variable, and select âWatchâ:
Alternatively, itâs also possible to create the watchpoint through the debugging console: watchpoint set variable self.counter
.
Then the breakpoint can be disabled, and the watchpoint will be triggered whenever the value of the variable changes.
Conclusion
Breakpoints and watchpoints are incredibly powerful features and, when used correctly, they can help speed-up the debugging process of an application in a very significant manner.
This article did not aim at being an exhaustive list of all the features breakpoints implement, so please feel free to read more about this topic. A good place to start being the command-line syntax to interact with the debugger.
You liked this article and you want to see more content like it? Feel free to follow me on Twitter: https://twitter.com/v_pradeilles