Debugging Chronicles: Exploring Breakpoints, Conditions, LLDB Commands, and Watchpoints

İrem Tosun
adessoTurkey
Published in
6 min readMay 29, 2024

When it comes to creating a product, the business layer is as crucial as the design. Now that we’ve seen how to debug view components, we can talk about debugging anything, especially the business logic.

Using Playground files

In most projects, there certainly needs to be some helper functions. If those functions are buggy, your app or a feature of your app will not work as expected. So, I recommend debugging/testing your helper functions, especially the ones that include complex business logic.

Testing some functions with the playground file.

You can simply add playground file into your project. All you need to do is to insert a new file from menu bar: File-> New-> Playground

Please keep in mind that if the playground file and the models called inside are in the same module, it won’t be a problem. Otherwise, you need to give public access level to your models in order to use them.

Use of Breakpoints

As a developer, I can’t imagine implementing complex features or fixing bugs without breakpoints. A breakpoint is a debugging tool that allows you to pause the execution of your program at a certain moment. Breakpoints in Xcode are essential tools for effectively debugging code.

Just click on the bottom area adjacent to the code line you wish to pause in order to establish a breakpoint. Run your application in debug mode after setting the breakpoint, and it will stop when it reaches it. From there, you can rapidly identify and address problems in your code by using Xcode’s debugging features, which include the debug console, variable inspection, and step-through execution. Breakpoints are customizable and can be turned on and off to meet your debugging requirements.

Use of LLDB Commands

During debugging sessions, Xcode’s LLDB (Low-Level Debugger) debugger offers an extensive command set for examining and modifying the state of your program in addition to allowing you to set breakpoints.

LLDB commands are somehow related to breakpoints, as you cannot run an LLDB command in the terminal without first placing a breakpoint.

Inspecting Your Code: Essential LLDB Commands to Examine

p Command

p(print), a basic LLDB command, lets you print a variable’s value in the debug console. For instance, entering p url will cause the url variable to print its current value.

Observing the variable with p command.

po Command

Another command similar to p is po. The po command will similarly print your object with all of its properties to the console.

Observing the object with po command.

e Command
The e command represents expression and is used for analyzing it. It is capable of executing any code in the current environment of the currently selected frame. This means you may use functions, assign values, and carry out other operations the way you would if you generated code in your source files.

Debugging the makeUrlString function with e command.

Use LLDB Commands for Modification on Run Time

Actually, the fundamental goal of utilizing the LLDB command for modification is to leave things unaltered.

p Command for Modification

The p command allows you to edit variables and run code within the context of the current debugging session. Here’s how you can edit variables with the p command:

Using p command for modifying the name of the person.
Screen before running p Command.

I absolutely haven’t made any changes in the implementation. Just ran p command for modification and I can see the difference on the screen afterwards.

After running the p command for modification, I have the value that I want to display for testing.

e Command for Modification

You can use e command and test a function during runtime without making any changes in the implementation as follows.

Running e command for altering a variable.
Previously, my query result variable is empty before running the command.

After running the command, the variable changed successfully. I wasn’t supposed to change anything inside the testButton() function.

The function was mocked somehow, giving me the updated value as needed.

As a conclusion, LLDB’s ability to modify variables in real-time enables dynamic adjustments to the behavior of your program, which can be especially useful when fine-tuning algorithms or experimenting with different configurations. By altering variables directly in the debugger, you can iterate more rapidly on your debugging process, refining your understanding of the problem and testing potential solutions iteratively.

Conditional Breakpoints

With Xcode’s advanced debugging capability, you may interrupt program execution only when specific criteria are satisfied by using a conditional breakpoint. This makes it easier to find and repair flaws in your code, especially when you want to look at issues that arise under particular conditions.

To set a conditional breakpoint, open the breakpoint inspector. Right-click on the blue breakpoint indicator. Select Edit Breakpoint from the context menu. This will open the Breakpoint Inspector.

Adding the condition with breakpoint inspector.

I have used this functionality to ensure that the pull functionality works as expected. The record count is initially 20, and to understand that pagination works, the record count must be greater than 20. I preferred to log a message in that case.

As a pull to get more records, conditional breakpoint worked and I saw a log message on the terminal.

Let’s be more compelling and edit this breakpoint to pause after ignoring 2 attempts. In this way, I am testing if I get at least 80 records after pagination.

Adding more conditions to breakpoint.
I can see that it works as expected.

Well, that functions as expected. As you can see, I verified that my pagination works as expected by using the conditional breakpoint. It is your call to use it in any way you need.

Obviously, it doesn’t only provide logging functionality. You can also run some debugger commands depending on a condition. In the screenshot below, when my search functionality runs, I have searched for ‘Morty’ when the user entered an empty string.

Used conditional breakpoint and a debugger command.

Add a WatchPoint

Instead of stopping the program’s execution when a line of code is encountered, watchpoints function similarly to breakpoints. Instead, when a particular variable’s value changes, they suspend the program. In situations where you are uncertain about the location or timing of a variable’s value alteration within your code, this capability becomes extremely handy.

In order to add a watchpoint to a variable, we need to add a breakpoint at first.

I want to watch the changes in vane rotation angle.

I simply right-click on the variable that I want to watch. I continue execution, and the execution pauses whenever the watched variable changes. This allows me to inspect the new value and see exactly where in the code the change has occurred.

Output of changes in the terminal.

Thank you for joining me on this deep dive into the world of debugging with breakpoints, conditions, LLDB commands, and watchpoints. Mastering these tools and techniques is crucial for efficient and effective software development. I hope this exploration has provided you with valuable insights and practical tips to enhance your debugging skills. Remember, debugging is an art, and the more you practice, the more proficient you’ll become. Happy debugging, and until next time, keep solving those challenging bugs with confidence and precision!

--

--