Advanced debugging with Xcode 🐛

Vincent Pradeilles
6 min readMar 5, 2018
Thanks to Anthony Tonev for the great animation & inspiration!

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

--

--

Vincent Pradeilles

French iOS software engineer, working in Lyon, France đŸ‡«đŸ‡·https://twitter.com/v_pradeilles https://youtube.com/channel/UCjkoQk5fOk6lH-shlm53vlw