Swift Function


The Ultimate Guide to iOS App Troubleshooting with Advanced Swift Debugging

In the life of every iOS developer, including those looking to hire Swift developers, a significant amount of time is spent troubleshooting and debugging applications. Debugging can often be challenging, especially when you are working with complex architectures and numerous third-party libraries. But with the right tools and techniques, you can transform this process from frustrating to enlightening.

The Ultimate Guide to iOS App Troubleshooting with Advanced Swift Debugging

In this article, we’ll discuss some advanced debugging techniques in Swift, along with examples, to help you conquer even the most mysterious bugs.

1. LLDB and the Command Line Interface

Most developers are familiar with setting breakpoints in Xcode and inspecting variables. But the LLDB debugger (Low-Level Debugger) has so much more to offer. 

Example: Let’s say you have a piece of code that manipulates a string but is failing mysteriously:

func manipulateString(_ input: String) -> String {
    // ... some complex manipulation ...
    return manipulatedString

You can use the `po` command in LLDB to print the description of an object:

po input

If you’re working with custom objects, try:

po customObject.description

2. Conditional Breakpoints

Sometimes you only want to pause execution under certain conditions. Instead of adding code-based checks, you can use conditional breakpoints.

Example: Consider you have a loop processing a large array, and you want to break when a certain condition is met:

for item in largeArray {
    // ... processing ...

Set a breakpoint inside the loop, right-click it in Xcode, select ‘Edit Breakpoint’, and add a condition like `item.id == targetID`.

3. Using the `@available` attribute

Sometimes bugs occur because certain code is executed on iOS versions that don’t support it. By using the `@available` attribute, you can ensure you’re not calling unsupported APIs.


if #available(iOS 14.0, *) {
    // Use iOS 14 specific APIs
} else {
    // Handle older versions

4. Watchpoints

When you’re unsure about where a variable is being modified, you can set a watchpoint. It will pause the execution whenever the value changes.


You have a variable:

var importantVariable: Int = 0

In LLDB, you can set a watchpoint:

watchpoint set variable importantVariable

5. Symbolic Breakpoints

These are perfect when you want to know whenever a specific method, even in Apple’s own frameworks, is being called.

Example: Break every time `viewDidLoad` is called:

– Go to Debug -> Breakpoints -> Create Symbolic Breakpoint.

– For Symbol, input `- [UIViewController viewDidLoad]`.

6. Memory Graph Debugger and Zombies

Memory issues like retain cycles and memory leaks can be notoriously hard to debug. Xcode’s Memory Graph Debugger is an invaluable tool in such cases.

Example: To find a retain cycle:

– Run your app.

– Click on the Memory Graph Debugger icon in Xcode.

– Look for objects that should have been deallocated but are still in memory.

For over-released objects, enable Zombie Objects in your scheme’s diagnostics to keep them around as “zombies” and get a warning when the app touches them.

7. Using `assert()` and `precondition()`

`assert()` and `precondition()` are ways to check conditions during debugging and release, respectively.


func divide(_ a: Int, by b: Int) -> Int {
    assert(b != 0, "Division by zero is not allowed")
    return a / b

8. Custom LLDB Commands

You can extend LLDB with custom Python scripts, which can be incredibly powerful.

Example: Automatically print the `description` of all `UIView` subclasses:

import lldb

def printUIViewDescriptions(debugger, command, result, internal_dict):
    # Fetch all UIView instances and print their descriptions

lldb.debugger.HandleCommand('command script add -f customCommands.printUIViewDescriptions printViews')

Use `printViews` in LLDB to execute your custom command.


Mastering debugging in Swift is about knowing the tools at your disposal and understanding how to use them effectively. The techniques discussed here will surely help you uncover and fix issues in your iOS applications faster and more efficiently. Remember, every bug you find and fix is a step towards a more robust and reliable app. Embrace the challenge, and happy debugging!

Previously at
Flag Argentina
time icon
Experienced iOS Engineer with 7+ years mastering Swift. Created fintech solutions, enhanced biopharma apps, and transformed retail experiences.