Logo for tanaschita.com

Understanding LLDB print commands for iOS debugging with Xcode

Learn the difference between po, p, and v to inspect variables in Xcode's console.

19 May 2025 · 4 min read

LLDB is a powerful tool for exploring and debugging iOS applications at runtime.

When we set a breakpoint in our code, Xcode pauses the app and gives us a few ways to inspect the current state. We can either use the variable viewer in Xcode's sidebar or enter LLDB commands directly in the console.

To inspect variables through LLDB, we typically use three print commands:

  • v for direct memory inspection
  • p for evaluated expressions
  • po for object descriptions

Let's walk through how each one works and when to use them.

Sponsorship logo
Architecture & Design Patterns for iOS
This book is a practical guide to essential architectural principles and design patterns for iOS development. It covers strategies for building maintainable apps with Swift and SwiftUI, including dependency injection, navigation, common patterns, and modularization.
LEARN MORE

LLDB command v

The v command is an alias for frame variable. It reads what's currently in memory and prints an LLDB-formatted summary of the value. Xcode uses this command behind the scenes for its variable viewer.

(lldb) v bird
(ExampleApp.Bird) bird = {
name = "kea"
conservationStatus = en
}

This command is fast and safe because it doesn't compile or evaluate any expressions. It only works with stored properties - computed properties or function calls will result in an error:

(lldb) v bird.conservationStatus.title
error: "title" is not a member of "(ExampleApp.ConservationStatus) bird.conservationStatus"

LLDB command p

The p command is an alias for expression. Unlike v, it compiles and executes code on the spot, which means we can evaluate expressions, access computed properties, and call functions.

(lldb) p bird
(ExampleApp.Bird) $R2 = {
name = "kea"
conservationStatus = en
}

For a computed variable:

(lldb) p bird.conservationStatus.title
(String) $R3 = "endangered"

LLDB command po

The po command is also an evaluated expression, but it prints a human-readable description of the object instead of the LLDB-formatted structure. Internally, it calls expression --object-description.

If the object conforms to CustomDebugStringConvertible, po uses the custom debug description we provide.

extension Bird: CustomDebugStringConvertible {
var debugDescription: String {
return "The bird \(name) is \(conservationStatus.title)"
}
}

Which results in the following:

(lldb) po bird
▿ The bird kea is endangered
- name : "kea"
- conservationStatus : ExampleApp.ConservationStatus.en

If no custom description is provided, po falls back to the system’s default.

Conclusion

In most cases, using p or po gives us the most flexibility. They evaluate expressions and work with computed properties and methods. However, they do add a bit of runtime overhead since they compile and execute code.

If we're dealing with timing-sensitive code, such as multithreading bugs or race conditions, it may be better to use the v command. It doesn't disturb the execution environment as much because it doesn't evaluate code, just reads memory.

For these situations, we can even set breakpoints that don't pause the app. In Xcode's breakpoint editor, we can enable the option to Automatically continue after evaluating actions and log the output with v, so we can debug without affecting the timing.

Sponsorship logo
Preparing for a technical iOS job interview
Preparing for a technical iOS Job Interview with over 300 questions & answers. Covering Swift & Objective-C, SwiftUI & UIKit, Combine, HTTP Networking, iOS File System, Core Data, Concurrency with async/await, Security, Automated Testing, Dependency Management, AI & Machine Learning and more.
LEARN MORE
Sponsorship logo
Architecture & Design Patterns for iOS
This book is a practical guide to essential architectural principles and design patterns for iOS development. It covers strategies for building maintainable apps with Swift and SwiftUI, including dependency injection, navigation, common patterns, and modularization.
LEARN MORE
Sponsorship logo
Become a sponsor of tanaschita.com
By publishing an article on different iOS topics every week, tanaschita.com is constantly growing in the developer community and may provide a great audience for you as a sponsor.
CLICK TO LEARN MORE

Newsletter

Image of a reading marmot
Subscribe

Like to support my work?

Say hi

Related tags

Articles with related topics

lldb

testing

xcode

ios

Changing runtime state with LLDB while debugging iOS apps

Learn how to use LLDB's expr command to modify variables at runtime.

30 Mar 2026 · 5 min read

Latest articles and tips

© 2026 tanaschita.com

Privacy policy

Impressum