Skip to content

Instantly share code, notes, and snippets.

@vincent-pradeilles
Created February 18, 2018 13:44
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save vincent-pradeilles/b431e37f9638cee2453c89ccb8caa49d to your computer and use it in GitHub Desktop.
Save vincent-pradeilles/b431e37f9638cee2453c89ccb8caa49d to your computer and use it in GitHub Desktop.

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 conso.le 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 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 commande like po myVariable, and then we resume the execution.

Of course, this manual operation will become very tedious if we need to perform 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"

// TODO add screenshot

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:

// TODO add screenshot

In this example the condition is quite simple, but more complicated expression 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 rest.

Once again, using "Edit Breakpoint..." the option is already waiting for us:

// TODO add screenshiot

Exception breakpoints

When an exception or an error is thrown and is not catched, 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 thrown 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 occurence of an error.

To do so, Xcode already offers two flavor of such breakpoints, depending on wether you are interested in Swift or Objective-C errors:

// TODO add screenshot

The great thing about them is that you can also edit them, in order to make even more tailored to your need, by filtering for a specific Swift.Error type, or triggering either when the error is thrown or when it is catched.

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:

// TODO add screenshot

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 this call.

Watchpoint

When you think about it, breakpoint are constructs that focus 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 runs.

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":

// TODO add screenshot

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 aimed 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.

@w-i-n-s
Copy link

w-i-n-s commented Apr 7, 2018

watchpoint set variable

thanks a lot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment