An Introduction to Xcode’s Debugger
I see a lot of questions on forums from iOS and Mac developers having issues with their code not working properly or crashing with cryptic error messages, like the following:
- Thread 1: signal SIGABRT
- Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
- EXC_CRASH (SIGTRAP)
- Unrecognized selector sent to instance
- Thread 1: EXC_BAD_ACCESS (code=2, address=0x102044190)
Many of these issues can be fixed quickly with the help of Xcode’s debugger. In this article I will show you the basics of Xcode’s debugger so you can find and fix bugs in your code more quickly.
Breakpoints
Breakpoints are fundamental to using debuggers. Breakpoints pause your app so you can debug it. If you want to debug an Xcode project, you will have to set at least one breakpoint.
Setting Breakpoints
The easiest way to set a breakpoint is to click on the left side of Xcode’s editor next to the line of code where you want your app to pause.
The blue arrow in the editor indicates a set breakpoint.
Disabling Breakpoints
Suppose you set a breakpoint inside the loop. You don’t want your app to pause every time you go through the loop. By disabling the breakpoint after going through the loop once, Xcode won’t pause at the breakpoint until you enable it.
Click on an enabled breakpoint to disable it.
Setting an Exception Breakpoint
Setting a breakpoint on a line of code works when you have an idea of where the problem is in your code. But if your app is crashing, it can be tough to find the source of the crash in your code.
Finding the source of crashes is where exception breakpoints come in. When your app crashes, it throws an exception. Setting an exception breakpoint pauses execution of your app when it crashes so you can locate the source of the crash.
To create an exception breakpoint, choose Debug > Breakpoints > Create Exception Breakpoint. A popover opens.
You shouldn’t have to change anything in the popover. Make sure the Exception menu is set to All and the Break menu is set to break on throw.
You can find more information on the common causes of app crashes in the Fixing and Avoiding Crashes in Swift Code article on this site.
Debug Area
Now that you set some breakpoints, you can build and run your project. When your app reaches a breakpoint, Xcode pauses the app, showing the debug area of the project window at the bottom of the window.
As you can see in the screenshot, there are three sections of the debug area.
- Debug bar
- Variables view
- Console
Debug Bar
The debug bar contains buttons to perform the most common debugging commands. There are two sets of buttons divided by a thin vertical separator. The first set has the following buttons, running from left to right:
- Show/hide the debug area
- Activate/deactivate breakpoints, which allows you to quickly toggle your active breakpoints with one click.
- Resume program execution
- Step over
- Step into
- Step out
The second set has the following buttons:
- Debug view hierarchy
- Debug memory graph
- Override appearance
- Simulate location
The buttons in the second set are beyond the scope of this article. Debugging the view hierarchy and debugging the memory graph could be the subject of their own articles.
Stepping
In the previous section you saw that the debug bar has three buttons for stepping through your code: step over, step into, and step out. When should you step over, step into, and step out?
You are going to step over code the most. When you step over a line of code, the debugger executes that line of code and moves to the next line. Unless the current line of code calls another function, you should step over that line.
If the current line of code calls another function, you may want to step into the function. Suppose you have a function A that calls function B. If you step over the call to B, the debugger goes through all the code in B and takes you to the next line in A. This behavior may be what you want, especially if you are making a call to a function in Apple’s frameworks, where you don’t have the source code.
But you may want to step through the code in B. To step through the code in B, step into the call to B in function A. The debugger will take you to the start of B, where you can step over the code in B line by line.
When you step into a function, you can use the Step Out button to go back to the previous function. If you are in B and want to go back to A, click the Step Out button.
Variables View
The variables view shows your app’s variables and their values. Sometimes it can be tough to find the value you want in the variables view. The variable you want may be nested inside data structures. The value may show up as a memory address instead of the real value. When the variables view doesn’t show what you want, you must resort to the console.
Console
The console shows any messages your app generates as it runs. If you have any print
statements in your code, the printed messages will appear in the console.
You can also use the console to run LLDB debugger commands. The LLDB page has a list of commands.
One common command is the po
command that prints out the contents of a variable. If you type a variable name, you’ll notice the console supports Xcode’s autocompletion.