Debugging in Xcode

a.k.a “Surely there must be an easier way than sticking NSLog everywhere!”

jon.lazar
4 min readOct 4, 2015

So, it turns out that like most things in Xcode there’s more to debugging than meets the eye. A whole lot more. If you’re anything like me you probably spend more time here:

Than you do here:

From what I can tell, that means you’re doing it right. Getting feedback from Xcode is a critical step in the understanding of how code works and perhaps more importantly, why things break. Fortunately Xcode provides us with a handy way of introspecting our code which may be easily missed:

What’s this LLDB thing?

According to Apple, LLDB is Apple’s “from the ground up” replacement for GDB, developed in close coordination with the LLVM compilers to bring you state-of-the-art debugging with extensive capabilities in flow control and data inspection.

LLDB lets us interact with the code directly, just like the terminal lets us interact with our machine directly. It’s pretty awesome. Like the breakpoint object navigator — you can access anything within the current scope of the breakpoint. So if you were in a method call you could access any passed parameters, or the local variables and objects. You can type just about any valid objective-c code that will fit on one line and expect it to work in the debugger with a few caveats (see below).

You can do things like:

p — print / po — print object

p print the values stored by primitive types (booleans, floats, integers,.etc.) or for non-primitives their memory address
po (print object) is print for objects and utilizes the objects description method to print its contents

This can be useful to inspect any value you would like or play around with the code to see what works and what doesn’t.

The $6 above is an internal LLDB variable which you can use if you choose (more on that below)

e— short for expr — or expression evaluation

Use e to enter your obj-c code into lldb as an expression which will be evaluated by LLDB.

Create objects on demand in LLDB — a few quick rules

  1. All variables must be preceded with a $
  2. Just like in Objective-C you need to specify variable types and use pointers when creating non-primitives

3. You must explicitly typecast everything when passing objects within method parameters. It’s a bit of a pain point but there are a few workarounds which I’ll cover next.

4. However, there are a few shortcuts to get around all of the typecasting for those of you lazier types. For starters, you can typecast any object that inherits from NSObject with id — cool. If you expect to be doing a lot of object creation this way, the laziest way I’ve found is to simply force import UIKit into LLDB which lets you skip typecasting altogether.

Changing variables directly in the code:

Note that there is a breakpoint on line 3

This modification via LLDB changes the actual running code so that once the process continues, anything referring to string will now be “Vanilla”. This can be useful to try different inputs to a method or validation in order to test it without having to rebuild the program every time.

Control Flow

You can also control the flow of the debugging process directly. These all behave the same way as the icons when clicked in the debugger:
n — thread step over
s — thread step in
c — process continue

Putting It All Together

Let’s say for some reason you were creating a Caesar cipher and hadn’t memorized the ASCII table so you looked up a solution from somewhere online and want to understand why it works (ahem). Below I’ll show how you can use the commands discussed above to test edge cases and different inputs using LLDB for lowercase single characters:

This is a lot less code than the solution I came up with!

Turns out this solution is pretty good and makes good use of devisors and simple math to make the Caesar cipher really easy to work with. The best part is this took all of 2 minutes to verify and understand using LLDB.

As with all of the tools at our disposal, striving to understand them just a little bit better can go a long way. Good luck and happy debugging!

--

--