po in LLDB with swift
That error sounds like it might be because DWARF is not telling LLDB where to find your self
object. Given the nature of Swift, LLDB needs to know the type of self in order to be able to inject an expression inside your local scope.
One way to find out if that is your problem is to do at the LLDB prompt:
(lldb) frame variable -L self
You are probably going to not see a location for it. Worth filling a bug report for, just to track your specific repro case.
Anyway, to get to the bulk of your question. In Swift, there is no language-sanctioned mechanism for "print description" like for ObjC, so while you can type po self
, unless self is an Objective-C type, you will pretty much see the same thing that "p self" or even "frame variable self" would tell you - which is entirely based on the LLDB data formatters mechanism. If you want to hook into that to customize the way your Swift objects look, the obligatory reference is: http://lldb.llvm.org/varformats.html
How to override what's printed for lldb po command, for a swift enum?
You're comparing apples and oranges, to some extent. po
and CustomStringConvertible aren't really very closely related.
CustomStringConvertible and description
dictate what you see when you convert the object to a String (hence the name). So in the debugger what you want to do is say po String(testEnum)
. (Or don't use lldb at all; just print to the console from the running program, using print(testEnum)
; that's really what CustomStringConvertible is for.)
The display when you say po testEnum
has to do with how the enum is reflected. If you don't like that, you would want to implement CustomReflectable — but I don't believe you really want to do that, as I shall argue in a moment. First, an example:
enum TestEnum : CustomStringConvertible, CustomReflectable {
case Value1(test:Int)
var description: String {
return "Test Enum"
}
func customMirror() -> Mirror {
return Mirror(reflecting:self.description)
}
}
Now po testEnum
will yield Test Enum
. But... why? Do you really want to throw away the splendid mirroring that an enum gives you nowadays? For the whole first year of Swift's life, we complained that po
on an enum gave no information at all, not even what case it was; here you are learning not only the case but also the associated value of that case. It seems terribly retrograde, not to say self-defeating, to want to eliminate that.
How to use _printHierarchy in LLDB console with Swift?
You point out how one shows the view controller hierarchy with:
po [[[UIWindow keyWindow] rootViewController] _printHierarchy]
You then say:
This works only if you are debugging code on Objective C. In Swift, however, this doesn't work.
Actually, this depends a little upon how you pause the execution of your Swift program. The issue is that the expression
command (which po
uses) will use Swift expressions in Swift frames, and Objective-C expressions in Objective-C frames. Thus this means that the po
behavior varies depending upon how the execution pauses:
You can, for example, press the "pause" button while the app is running:
If you do this, you will be able to use the above
po
syntax with the Objective-C expression without incident.If, on the other hand, you set a breakpoint inside your Swift code, you'll be in a Swift frame when you get to the
(lldb)
prompt. But you can explicitly tell theexpression
command that you want to use the Objective-C syntax with the-l
(or--language
) option:expr -l objc++ -O -- [[[UIWindow keyWindow] rootViewController] _printHierarchy]
This ability to specify the language in the expr
command is discussed in WWDC 2014 video Advanced Swift Debugging in LLDB.
What's the difference between p and po in Xcode's LLDB debugger?
Strip debug symbols during copy
In most answers they advice to set optimization to "none" but forget that this option should be set to NO (at least for debug configuration).
po Swift String unresolved identifier
This is most likely a bug in the debug information output. You can check this by grabbing the PC, for instance from register read pc
, and then doing:
(lldb) image lookup -va <PC VALUE>
That will print a bunch of stuff, but the last entries will be all the variables currently visible to the debugger, and where they live (in registers or memory.) If you don't see the variable there, then the debug information must have told lldb that the variable is not currently live.
If you can reproduce this in some example code you can make available, please file a bug with bug reporter.apple.com.
What happens when you print a Swift object (po) in lldb?
There's a known issue that Printable
is ignored by the Swift REPL (i.e., anything in a Playground or run by xcrun swift
at the command line) but recognized by the compiler (compiled apps in the simulator or xcrun swiftc
).
For example, here's the code of "foo.swift":
struct Person : Printable {
let name: String
var description: String {
return "\(name)"
}
}
let me = Person(name: "Nate")
println(me)
If I run it using the REPL, I get this:
$ xcrun swift foo.swift
foo.Person
But if I compile it first, and then run it, it uses the description
computed property:
$ xcrun -sdk macosx swiftc foo.swift ; ./foo
Nate
The DebugPrintable
protocol is useful if you want to be able to use the debugPrint
and debugPrintln
functions -- in compiled code, they print out an instance's debugDescription
property.
Evaluate Swift expressions in LLDB
Working with Swift code in LLDB /h3>
Most Swift code can be executed as part of LLDB if it's part of the stdlib with the right syntax. The key is to prefix type names with the symbol identifier $
. I've used $
even for variable names here (new LLDB improvements make this unnecessary) because I prefer to distinguish LLDB definitions.
Extensions /h4>
With improvements to LLDB, you can actually copy-paste the Swift code directly after expression.
I've added an example for your extension with $
symbols for clarity:
(lldb) expression
extension Collection where Self.Element == Int {
var $elementsOver30: [Self.Element]? {
return self.filter { $0 > 30 }
}
}
(lldb) po [32,31,4].$elementsOver30
▿ Optional<Array<Int>>
▿ some : 2 elements
- 0 : 32
- 1 : 31
Pressing Enter after expression
prompts a multi-line evaluation where we can input the remaining Swift code.
Structs/Class definitions /h4>(lldb) expression
struct $Person {
let name: String
}
(lldb) po let $pranav = $Person.init(name: "pranav")
(lldb) po $pranav
▿ $Person
- name : "pranav"
Reading a Swift instance from memory
(lldb) expression
struct $Person {
let name: String
}
(lldb) po let $pranav = $Person.init(name: "pranav")
(lldb) po $pranav
▿ $Person
- name : "pranav"
Sometimes, we need to read Swift code using Objective-C in LLDB. For example, if we have a Swift file with a View Controller:
class LoginViewController: UIViewController {
...
}
We can print the dynamic type of the result of a memory address as follows:
(lldb) expr -O --language objc -- 0x14160c260
<SharedSettings.LoginViewController: 0x14160c260>
View Swift docs /h4>
Use type lookup
to read a minified version of the type definitions:
(lldb) type lookup Equatable
protocol Equatable {
static func == (lhs: Self, rhs: Self) -> Swift.Bool
}
extension Swift.Equatable {
static func != (lhs: Self, rhs: Self) -> Swift.Bool
}
Related Topics
How to Line Break Long Large Title in iOS 11
Swift - Seeding Arc4Random_Uniform? or Alternative
Rotate an Object in Its Direction of Motion
Method' Is Ambiguous for Type Lookup in This Context, Error in Alamofire
Warning: Initialization of 'Unsafebufferpointer<T>' Results in a Dangling Buffer Pointer
Working with C Strings in Swift, Or: How to Convert Unsafepointer<Cchar> to Cstring
Turn Off Xcode's Unused Variable Warnings While Typing
Swiftui: Prevent Image() from Expanding View Rect Outside of Screen Bounds
Simultaneous Gesture Recognition for Specific Gestures
Converting Swift Array to Cfarray in Xcode 8 (Swift 3)
Unsaferawpointer Assumingmemorybound VS. Bindmemory
How to Filter Characters from a String in Swift 4
How to Get Start and End of the Week in Swift
Can't Understand How Collision Bit Mask Works
Add Switch in Uitableview Cell in Swift
Swiftui Foreach Based on State Int
Swift Combine Sink Stops Receiving Values After First Error
How to Set the Alpha of an Uiimage in Swift Programmatically