Logo for tanaschita.com

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

When developing an iOS app, we often need to bring the app into a very specific state, for example when reproducing bugs or testing edge cases.

LLDB provides a powerful way to achieve that: we can modify values at runtime using the expression command, without touching our source code or restarting the app.

Let's take a look at how this works.

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

Modifying values from the console

When our app pauses at a breakpoint, we can use Xcode's console to change a variable to a state we need.

Let's imagine, we are trying to fix a bug that only is reproducable for birds that have a critically endangered conservation state. When a breakpoint hits the relevant line, let's at first print the bird's conservationStatus in Xcode's console:

(lldb) po bird.conservationStatus.title
"endangered"

Since we'd like to test the app with a different conservationStatus, we can use the expr (or its shorthand p) command to change it:

(lldb) p bird.conservationStatus = .cr

When printing the conservationStatus again, we get:

(lldb) po bird.conservationStatus.title
"critically endangered"

From here, we can continue execution and observe how the app behaves under this modified state.

This is especially useful when a bug only appears under rare conditions that are otherwise difficult to reproduce.

When this approach is useful

In practice, this is not the only way to approach these situations. In many cases, we might simply hardcode a value directly in the code to reach the desired state and avoid committing that change. This approach is often more explicit and easier to reason about, especially when working with Swift's type system.

Modifying state with LLDB becomes useful in situations where reproducing a specific state is otherwise time-consuming or difficult.

For example, we might already be several screens deep in a navigation flow and want to test a specific edge case. Instead of restarting the app and navigating back to the same point, we can modify the state directly at the breakpoint:

expr result = .error

This approach is also helpful when experimenting with different values during debugging. Instead of repeatedly changing code and rebuilding, we can quickly explore different scenarios:

expr config.isEnabled = false

Limitations

While this technique is powerful, there are a few important limitations:

  • Constants (let) cannot be modified: attempting to assign a new value will result in an error.
  • Value types may behave unexpectedly: when working with structs, we are mutating a copy in some contexts. The change may not propagate as expected.
  • SwiftUI state isn't always mutable this way: properties like @State may not respond reliably to LLDB mutations.

Automating changes with breakpoint actions

When reproducing a bug, we sometimes want a variable to always have a certain value without typing the command every time in the console.

In this case, we can use a breakpoint action.

  1. Set a breakpoint at the relevant location
  2. Right-click the breakpoint and choose Edit Breakpoint
  3. Add an action of type Debugger Command
  4. Enter the command:
expr bird.conservationStatus = .cr
  1. Enable Automatically continue after evaluating actions.

Now, every time the breakpoint is hit, LLDB applies the change and continues execution immediately. This allows us to consistently reproduce a specific scenario without interrupting the flow.

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

xcode

ios

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

Latest articles and tips

© 2026 tanaschita.com

Privacy policy

Impressum