Skip to content
Go back

Debugging Tips

Here are a couple of my favorite debugging tricks and tips I use while working on Swift projects.

Configure your .lldbinit

First, most of us want to work with Swift, not Objective-C, but depending on your project setup, you might have Objective-C enabled by default. We have 2 options:

  1. We can manually change the language during the lldb session by callingsettings set target.language swift
  2. We can create a .lldbinit file in our home directory and add it there to be the default for all debugging sessions e.g. echo 'settings set target.language swift' > ~/.lldbinit followed by chmod +x ~/.lldbinit

Furthermore, .lldbinit is a great place to add additional things that you’ll be using across your projects. Here is a part of mine:

settings set target.language swift

breakpoint set -r NSWindow.initialFirstResponder --one-shot true --auto-continue true
breakpoint command add
e import AppKit
e import Foundation
e func $vc<T>(_ input: T) -> NSViewController { unsafeBitCast(input, to: NSViewController.self) }
e func $view<T>(_ input: T) -> NSView { unsafeBitCast(input, to: NSView.self) }
DONE

breakpoint set -n UIApplicationMain --one-shot true --auto-continue true
breakpoint command add
e import UIKit
e import Foundation
e func $vc<T>(_ input: T) -> UIViewController { unsafeBitCast(input, to: UIViewController.self) }
e func $view<T>(_ input: T) -> UIView { unsafeBitCast(input, to: UIView.self) }
DONE

This allows me to use memory address to get info about my types easily:

po $vc(0x128027ad400)

Notes:

If the first character of your user defined variable is a $, then the variable’s value will be available in future expressions, otherwise it will just be available in the current expression.

Leverage frame variables

Most Swift engineers are used to using print object or po for short, but there is an alternative that often works faster and works in cases when po might fall short: frame variable or v

The short alias was added back in Xcode 10.2, and here’s Apple note about it

The LLDB debugger has a new command alias, v, for the **“frame variable” **command to print variables in the current stack frame. Because it bypasses the expression evaluator, v can be a lot faster and should be preferred over p or po. https://developer.apple.com/documentation/xcode_release_notes/xcode_10_2_release_notes

🤔

v and vo works for stored properties but won’t work for computed ones. You’ll need po for those.

Here’s an example: Image You can add additional flags to it to get even more information by adding **-O **option to it.

Use expressions

The aforementioned **po**is an alias for a **e -O –**which will evaluate the object and try to call description method on it if it exists, it will evaluate the given expression and then try calling description method on it.

But expressions are more valuable than that, and it would be worth using them directly instead of relying on **po**.

We can interact with our system by leveraging e or expression, this can be very convenient when dealing with variables:

e var $vc = self.controller
e $vc.view.layer.borderColor = CGColor.red
e CATransation.flush() // Refresh the core animation screen without having to end debugging session

Observe the system

We can leverage breakpoints for many things, from changing default inputs into fields (e.g. login forms): To using debugger commands to build symbolic breakpoint chains, e.g.

breakpoint set --name "[CommandBarInputContainer layout]"

Would create a breakpoint on the layout call of my NSView, now this would be too frequent, but I could set it up as part of another breakpoint execution, e.g. when the user changes the text input.

I could also use --one-shot true to only execute the breakpoint once per trigger.

Watch variable change

We can add breakpoints when a variable changes, either through Xcode UI or lldb command:

watchpoint set variable self.homeViewController Watchpoint UI Then whenever that variable changes, Xcode will stop our debugging session and give us info like this: We can then print and interact with that value

po value
 Optional<NSViewController>
 some : <HomeButton.HomeViewController: 0x13407cf3ac0>

What are your favorites?

Let me know what your favorite tips or lldb commands are!


Share this post on:

Previous Post
Widget architecture - part 1
Next Post
TCA Performance and Multi-Store