Advanced Debugging with XCode and LLDB, Part 1

Reading Time: 7 minutes

This week, a WWDC talk about debugging in XCode is making me rethink some things.

So I decided to write about it. It’ll be a three part series:

  1. An outline of the techniques demonstrated in the talk (this post)
  2. How the talk challenged my views both on XCode and on learning a new stack
  3. Additional XCode debugging features not covered in the talk

Thank you to the talk hosts, Chris Miles and Sebastian Fischer, for unwittingly enabling this tangent 😃.

Here‘s where Apple keeps the video of the talk:

apple ios debugging talk

At that link, you can also:

  • Get a transcript of the talk
  • Download an HD version of the video (the low-resolution version embedded on the site itself makes it hard to read the text in the IDE)
  • The slides (They don’t use these in the presentation, opting instead for live demos, which I think is more clear. But, if you like, the slides are there).

Outline: What the Talk Covers, in Pictures

We can set a Debug tab in the tab bar in the “Pauses” section of “Edit Behaviors.” 

Here’s how you get to that:

Screen Shot 2020-04-03 at 9.48.16 AM

Immediately after this, Chris demonstrates the elements of debugging in XCode that I see developers use the most often: setting a breakpoint (by clicking on a line of code), and printing out a value (by typing po [value] after the (lldb) prompt in the console).

Then we get fancy.

We can inject a line of code while paused at a breakpoint.

(lldb) expression self.view.backgroundColor = .green

We can also automate the injection of a line of code at a breakpoint without changing the code itself:

right-click breakpoint —> “Edit Breakpoint”, then

Screen Shot 2020-04-03 at 11.27.10 AM

We don’t need to know a specific line to set a breakpoint if we know which method we’d like to inspect at runtime.

Here’s how we add a symbolic breakpoint:

Screen Shot 2020-04-03 at 11.34.45 AM

We then type in the method’s caller and name. This one is in Objective-C because it refers to a method happening in the Objective-C code of UIKit.

Screen Shot 2020-04-03 at 11.37.37 AM

Once we pause, LLDB offers us pseudo-registers to access information about that call of the method.

(lldb) $arg1 —> UINavigationBar <[Some memory address]> (the selector)

(lldb) $arg2 —> backgroundImage: (the argument label)

(lldb) $arg3 —> UIImage <[Some memory address]> (the first parameter)

We can set a condition under which we’d like a breakpoint to be triggered.

Screen Shot 2020-04-03 at 11.46.01 AM

We can set a breakpoint to only be triggered once and be removed for subsequent calls on this line:

Screen Shot 2020-04-03 at 11.46.01 AM

We can use a breakpoint to skip a line of code.

Screen Shot 2020-04-03 at 11.54.14 AM

There are a few ways to print output from LLDB…

Screen Shot 2020-04-03 at 12.00.07 PM

And if we don’t like those, we can implement our own:

We make our own debug descriptions by having the objects conform to the CustomDebugStringConvertible protocol, like so:

Screen Shot 2020-04-03 at 12.16.23 PM

We can also set watch points to be notified when specific variables’ values are changed:

Screen Shot 2020-04-03 at 12.20.21 PM

And we can review our watchpoints in the debugging menu:

Screen Shot 2020-04-03 at 12.20.46 PM

We can print the values of Objective C objects.

Screen Shot 2020-04-03 at 12.44.00 PM

We can set aliases for LLDB Commands.

For example: (lldb) command alias printobjc expression -l objc -O --

And we can even import a file full of LLDB aliases to customize our debugging command repertoire.

If we’re messing with views in the debugger and they’re not updating, we can force XCode to update the iOS frame buffer.

(lldb) CATransaction.flush()

Chris then aliases this command to the 🚽 emoji, because no tech talk is complete without toilet humor, I guess. To be fair, I have also included a toilet reference in a talk before.

When the app is running in a simulator, we can debug the view hierarchy in XCode.

Screen Shot 2020-04-03 at 1.05.31 PM

If we have an alert controller showing when we debug the view hierarchy, that will appear on the hierarchy as well:

Screen Shot 2020-04-03 at 1.40.56 PM

We can also look at constraints…

Screen Shot 2020-04-03 at 1.10.10 PM

…and set constraints to different values in LLDB:

(lldb) e [[(NSLayoutConstraint *) 0x7654f43) setConstant -30]

(lldb) CATransaction.flush()

(The “e” in the above example aliases to “expression”.)

We can edit the scheme to log malloc stacks for all objects.

Screen Shot 2020-04-03 at 1.24.36 PM

We can enable environment overrides while our app is presented in the simulator.

This allows us to see how our UI responds to different view modes (like dark and light) as well as different accessibility features like dynamic types (for increasing font size), button shape (for making tap targets easier to reach), and reduce motion (for making the app run faster or mitigating animations that trigger epilepsy—sidenote, please do not put animations in your app that trigger epilepsy).

I also inverted the colors for this screenshot because it makes the angry bird look somehow even more enraged, which makes me laugh.

Screen Shot 2020-04-03 at 2.00.01 PM

Pretty cool, right?

Maybe learning about one of the features listed above has prompted you to open up XCode and try it for yourself, or even watch the original talk. Here’s the first part of a fantastic three-part tutorial, with starter code for both Objective-C and Swift, in case you want to dive deeper. Props to Fady Derias for that.

And while I highly recommend the talk, I also think this outline will be the least informative of the three pieces I’ll be publishing in this series. In the next post, we’ll talk about how these features fit into the broader cultural context of XCode users and how this talk has informed some changes in my approach to learning a new programming language or stack.

If you liked this piece, you might also like:

The Leveling Up Series (a perpetual favorite for gearheads like yourself)

The Books Category, to which I’m slowly adding all the blog posts where I reflected on a book

The History of API Design Series (prepare to have your sacred cows threatened)

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.