PO vs P vs V in LLDB of Xcode
Tags: lldb, swift, ios
Published: 2024-07-11 17:09:31

## What is LLDB?
LLDB is Xcode's integrated low-level debugger, essential for examining and debugging applications across Apple's platforms. It enables developers to set breakpoints, inspect variables, and navigate through code execution to diagnose and resolve issues efficiently. With support for both graphical and command-line interfaces, LLDB streamlines debugging workflows from simple variable checks to complex debugging tasks

## How to Interact with LLDB?
LLDB allows different ways to interact with the application. such as **po**, **p** and **v**

## Let's take a look at below code Snippet.
```swift
import Foundation

enum ClassName {
    case c1;
    case c2;
    case c3;
}

class Person {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
    
    func setName(name: String) {
        self.name = name
    }
}

class Student: Person {
    
    var className: ClassName
    
    init(name: String, age: Int, className: ClassName) {
        self.className = className
        super.init(name: name, age: age)
    }
}

let student = Student(name: "vinay", age: 26, className: .c1)

struct StudentStruct {
    let name: String
    let age: Int
}

let studentStruct = StudentStruct(name: "vinayStruct", age: 26)


```

## What is po?
In Xcode, po stands for "print object," which is used to print the description of an object during debugging. When you use po followed by a variable name in the debugger console, it displays detailed information about that object.

For example, if you want to print the variable `student`, executing `po student` in the debugger console will display the object's description or address.
```shell
po student
```
![po-student](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m8nczafqmgcz7ukgvnp7.png)

For a variable like `studentStruct`, which is a struct type and already provides a default debugDescription method, `po` calls this method to show the detailed description of the object.

```shell
po studentStruct
```
![po-studentStruct](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cqtz9h4f22o1e115zjck.png)

If you confirm the Student class to `CustomDebugStringConvertible` and override its `debugDescription` method as shown below:

```swift
class Student: Person, CustomDebugStringConvertible {
    var debugDescription: String {
        return "Student(\(self.name), \(self.age))"
    }
    
    var className: ClassName
    
    init(name: String, age: Int, className: ClassName) {
        self.className = className
        super.init(name: name, age: age)
    }
}

let student = Student(name: "vinay", age: 26, className: .c1)

```

By implementing CustomDebugStringConvertible, you provide a custom implementation for the debugDescription property. When you use po student in the debugger console in Xcode, it automatically uses this custom debugDescription method to print a formatted description of the student object, incorporating its name, age, and any other relevant properties or state.


![po-student](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j1g5ca9hy0ryrpo6t5oj.png)

This demonstration clearly illustrates that po is utilized to display the object's description while debugging.

> That's all `po` does? no, It can do more. you can even call the string methods on the `name` variable of the `student`

```shell
po student.name.uppercased()
```
![print-student](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nqt1nnyv3plnxh6f6n1d.png)

> In general, It can evaluate any arbitrary expression.

> In fact, po is alias for the command `expression`.

example:
```
expression --object-description -- student
```

![print-student](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/on0a4n2p27deonhocbnm.png)

> you can even create your own `po` commands

```
command alias my_po expression --object-description --
my_po student
```

![my_po-student](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nj0dukfzgee5vlmagff4.png)

To unalias the created one use below command
```shell
command unalias my_po
```

## What is p?
This is a second way of printing a variable in LLDB. You can think it as print without object description.

```shell
p student
```
![p-student](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9duhsgf398dfztcyf2z2.png)

1. The representation differs slightly from the one provided by `po`. But it is equivalent as it gives the same information about the instance variables
2. `p` is an alias for the command `expression` but without `--object-description` flag
3. This `p` gives an incremental name to the result like $R0, $R1 etc.
4. `p` uses DataFormatters to print the information. Anyway, we are not covering DataFormatters in this tutorial.

> If you use `p` in the latest Xcode version variables ex: $R0 `name` is not showing. But it is showing if you're using the `expression` command. I am not sure why.


![p-student](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a4so641yb6jl6ge6gzv0.png)


## What is v?
To understand v, declare a variable `studentWithBaseType` as `Person`, not `Student`.

```swift
let studentWithBaseType: Person = Student(name: "vinaywithbasetype", age: 26, className: .c1)
```

Since `studentWithBaseType` is of type Person, you cannot read properties specific to Student without casting it first, like accessing className on studentWithBaseType, which Swift's compiler does not allow. To read it, you must cast it:

```swift
(studentWithBaseType as! Student).className
```

Similarly, LLDB dynamically resolves variable types only in expressions. Attempting to access properties directly on the result in LLDB results in an error, as shown below:


![v-student](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eivoqnplmol1ewi3mgy4.png)

But By using `v` you can read the variables of the actual type Student in the LLDB console

```shell
v studentWithBaseType.className
```

## Differences
### po (print object):
**Use:** Print detailed object descriptions during debugging, especially useful for custom debug descriptions (CustomDebugStringConvertible).
**When to Use:** Use po when you need a formatted and detailed view of an object's state, including custom debug descriptions.

### p (print):
**Use:** Provides basic information about variables and objects without the detailed object description.
**When to Use:** Use p for quick checks on variable values or when detailed object description isn't necessary, providing a concise view of the variable's state.

### v (dynamic resolution):
**Use:** Used for dynamically resolving types in LLDB expressions, essential when dealing with base types containing more specific class types.
**When to Use:** Use v to dynamically resolve and access properties specific to a subclass or more detailed class type within LLDB expressions.

## Conclusion:
LLDB in Xcode offers powerful tools (po, p, v) for developers to debug applications comprehensively, from simple variable checks to complex debugging tasks, improving overall code quality and performance

for in-depth understanding refer this Apple World Wide Developer Conference - WWDC2019 [Resouce](https://developer.apple.com/videos/play/wwdc2019/429)