1

Say you have a custom object which has a custom description like so:

class CustomObject {

    var customDescription: String {
        return "Title: Hello, \n Subtitle: World"
    }
}

Is there a way to have the line break \n work in the console when printing it using the po command in the LLDB console?

Right now LLDB prints the \n as part of the text and doesn't process it:

po object.customDescription
> "Title: Hello, \n Subtitle: World"

Where the desired result is:

po object.customDescription
> Title: Hello
  Subtitle: World

Do you have any solution for this?

fearmint
  • 5,276
  • 2
  • 33
  • 45
Thomas
  • 2,003
  • 18
  • 30
  • Inside a Swift Playground I observe your desired behavior. `let object = CustomObject.init() print(object.customDescription)` – fearmint Aug 15 '17 at 14:00
  • 1
    @JoePasq I'm sorry after looking more carefully I realised that it actually only doesn't work when using `po` which is what I would like to get to work! – Thomas Aug 15 '17 at 14:41
  • 2
    Okay that explains it, thank you. Please see this question. https://stackoverflow.com/questions/34278238/print-string-with-newlines-with-lldb#34297857 – fearmint Aug 15 '17 at 14:46
  • 1
    You have to implement a new Data Formatter in LLDB. Here's a quick intro: https://lldb.llvm.org/varformats.html – Code Different Aug 15 '17 at 20:48
  • This looks very promising I'm going to try it out thank you both! – Thomas Aug 16 '17 at 09:26

2 Answers2

13
po object.customDescription as NSString
Perlguy
  • 982
  • 10
  • 25
4

I don't want to discourage you from making an lldb data formatter for your classes. They have the advantage over po that they give lldb a way to show you a summary representation of your data without having to call code in the running program. Also, if you use Xcode, the Xcode locals view will show your data formatters automatically.

But to clear up the way po works:

The lldb po command works by calling the language-specified description method for the object that the expression you provide resolves to. So for instance in your example, you were seeing the result of the description method for the Swift String class, which displays the "programmer's view" of the string.

In the case of Swift, there are a couple of ways to provide a description. The simplest is to implement the CustomStringConvertible protocol:

class CustomObject : CustomStringConvertible {

    var description: String {
        return "Title: Hello,\n Subtitle: World"
    }
}

func main()
{
  let my_object = CustomObject()
  print (my_object)
}

main()

Then when you debug this, you see:

(lldb) br s -p print
Breakpoint 1: where = desc`desc.main() -> () + 27 at desc.swift:11, address = 0x000000010000116b
(lldb) run
Process 69112 launched: '/private/tmp/desc' (x86_64)
Process 69112 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x000000010000116b desc`desc.main() -> () at desc.swift:11
   8    func main()
   9    {
   10     let my_object = CustomObject()
-> 11     print (my_object)
                 ^
   12   }
   13   
   14   main()
Target 0: (desc) stopped.
(lldb) po my_object
Title: Hello,
 Subtitle: World

(lldb) c
Process 69112 resuming
Title: Hello,
 Subtitle: World
Process 69112 exited with status = 0 (0x00000000) 

Note here that both po and the swift print function render your object the same way.

If you want separate debug and print descriptions, then you also implement CustomDebugStringConvertible which requires a debugDescription property. Then po will print the debugDescription but print will print the description.

If you want to get fancier, or want to have po represent the "structure" of your object the way the po result for Swift Arrays (for example) does, you can make a custom Mirror for your class. There's documentation on that here:

https://developer.apple.com/documentation/swift/mirror

and if that isn't clear, the implementation of Mirrors is in the swift sources in:

https://github.com/apple/swift/blob/master/stdlib/public/core/Mirror.swift

Alex Zavatone
  • 4,106
  • 36
  • 54
Jim Ingham
  • 25,260
  • 2
  • 55
  • 63
  • The solution was so simple... Thanks! – Thomas Aug 07 '18 at 08:09
  • This is nice, but Objective-C actually obeys and displays the line feeds when you po the string. On the other hand, you can also enter print in the console and linefeeds are displayed. – Alex Zavatone Dec 12 '19 at 00:05