DEV Community

vinaykumar0339
vinaykumar0339

Posted on

PO vs P vs V in LLDB of Xcode

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.



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)




Enter fullscreen mode Exit fullscreen mode

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.



po student


Enter fullscreen mode Exit fullscreen mode

po-student

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.



po studentStruct


Enter fullscreen mode Exit fullscreen mode

po-studentStruct

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



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)



Enter fullscreen mode Exit fullscreen mode

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

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



po student.name.uppercased()


Enter fullscreen mode Exit fullscreen mode

print-student

In general, It can evaluate any arbitrary expression.

In fact, po is alias for the command expression.

example:



expression --object-description -- student


Enter fullscreen mode Exit fullscreen mode

print-student

you can even create your own po commands



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


Enter fullscreen mode Exit fullscreen mode

my_po-student

To unalias the created one use below command



command unalias my_po


Enter fullscreen mode Exit fullscreen mode

What is p?

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



p student


Enter fullscreen mode Exit fullscreen mode

p-student

  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

What is v?

To understand v, declare a variable studentWithBaseType as Person, not Student.



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


Enter fullscreen mode Exit fullscreen mode

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:



(studentWithBaseType as! Student).className


Enter fullscreen mode Exit fullscreen mode

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

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



v studentWithBaseType.className

Enter fullscreen mode Exit fullscreen mode




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

Top comments (0)