Breakpoints are one of the most basic elements of debugging a program.
You may already be familiar with using them in Xcode or may have accidentally set one after trying to select an error or warning in the gutter. In their most basic form, they halt the flow of a program. In this article we will explore some of their more advanced uses.
One of the easiest ways to get started with breakpoint options is right-clicking a breakpoint and selecting the Edit Breakpoint… option. From here you will see a screen similar to this:
This dialog gives you several different customization options for your breakpoint. Conditional breakpoints will only break when the condition is true, and any valid code that evaluates to a boolean can be used here. You can use any variable that is available in the scope of the breakpoint. The condition will only be evaluated at the breakpoint — even if the condition as true, the program will not break if the breakpoint is not reached. You can set the breakpoint to ignore the first couple of passes too. This can be useful if you know you are calling a function multiple times, but only want to break on the last call . Another useful instance is dealing with a UIViewController and you want to see what happens when a view appears, but only when it reappears and not on the first view.
In this example, I make the breakpoint a conditional breakpoint that will only stop when the variable fahrenheit is greater than or equal to 100. It is also possible to access the celsius and celsiusString variables since they are also in scope when the breakpoint is reached; the condition could be set to break if the celsius variable is greater than 38 instead.
Within this dialog you can also set up one or more actions to be performed each time the breakpoint is hit. I have decided I want a to print a log message:
Within the log message you also have access to variables from the scope with the expression syntax (@fahrenheit@), the name of the breakpoint (%B) and how many times the breakpoint has been hit during the current execution (%H). Any valid code can be put in an expression statement. I decided to print out the temperature in Fahrenheit. I also had the breakpoint immediately resume after executing the action since I am only interested in the log message.
Having a breakpoint resume after performing an action has several useful applications. For example, if you are testing a sign-in flow and want to remove credentials on each load of the view without having to sign out first, you can set a Debugger Command action to clear the stored credentials and have it automatically resume afterwards.
Or if you want to test that the program is creating a log file correctly, you can set a Shell Command action to remove the log file before each write to the log file.
Perhaps you want to record the state of your program every time it enters a certain function; you could add an AppleScript command to insert some state information into an external text editor through its AppleScript API. These are just some of the options available and I encourage you to explore the actions available yourself!
Another useful tool for working with breakpoints is the Breakpoint Navigator (⌘7). From here you can see all of the breakpoints in your project at a glance and create special breakpoints.
With an Exception Breakpoint, you can break when an exception in Objective-C or C++ is thrown. This will break even if the exception is caught and never bubbles up to your application layer! This could happen if you trigger some in-between state within a framework with you code, but the exception is caught before reaching you. You can choose to break either where the exception is thrown or where in the code it is caught. This can be really useful if an exception is caught several layers away from where it is thrown.
Symbolic Breakpoint… is a powerful breakpoint, it’s like a regular breakpoint, but it does not require the source to set a breakpoint. For a symbolic breakpoint, all you need is a name and you can break on it! In this example, I want to see when the internal method _sanitizeText: is called. The format for a symbolic breakpoint is a modified Objective-C function header: the instance or class specifier, an opening bracket, the class name, the method name without parameter types or names, and then finally the closing bracket.
Test Breakpoint allows you to peek under the hood when a test case fails and see what caused the test to break.
Next to the + sign are two more tools. The checkmark breakpoint allows you to filter out the breakpoints that are not enabled. This is great if you like to keep many breakpoints, but only have a select few enabled at a time. To help with filtering, there is also a text box. It will filter out any breakpoints that do not match the text in the box; this can be really helpful when you want to find all your breakpoints that are in methods that start with convert for example.
Hopefully this article has shown you a few more ways you can use breakpoints to debug your program. With these extra features you should be finding those bugs in no time!
P.S. You can quickly remove a breakpoint by dragging the breakpoint out of the gutter!