-1

I have a tree of UIViews i'm trying to make sense of: UIPageViewController height is a status bar height too high and somehow the bottom is foobar somewhere in the hierarchy descends below the window real estate height wise. Here's the chronicle of my woes with lldb:

(lldb) p (*(UIView*)0x83fcc6d0).accessibilityIdentifier
error: 'UIView' does not have a member named 'accessibilityIdentifier'
(lldb) p ((UIView*)0x83fcc6d0).accessibilityIdentifier
error: property 'accessibilityIdentifier' not found on object of type 'UIView *'
(lldb) p ((UIView*)0x83fcc6d0)->accessibilityIdentifier
error: 'UIView' does not have a member named 'accessibilityIdentifier'
(lldb) p (*(UIView*)0x83fcc6d0).superview
error: 'UIView' does not have a member named 'superview'
(lldb) p (*(UIView*)0x83fcc6d0).superView
\error: 'UIView' does not have a member named 'superView'
(lldb) v (*(UIView*)0x83fcc6d0).superView
(lldb) po (*(UIView*)0x83fcc6d0).superView
error: 'UIView' does not have a member named 'superView'
rmaddy
  • 314,917
  • 42
  • 532
  • 579
Anton Tropashko
  • 5,486
  • 5
  • 41
  • 66
  • 1
    Probably duplicate of https://stackoverflow.com/questions/29441418/lldb-swift-casting-raw-address-into-usable-type (though I have answered the question; perhaps I should have just closed as a dupe instead). – matt Apr 08 '19 at 17:58
  • yes, it seems to be a dup. I haven;'t gotten to check both replies for validity just yet. – Anton Tropashko Apr 12 '19 at 11:49

2 Answers2

1
  1. You've got too many asterisks.

  2. You can't use property notation.

  3. You need to use po.

So for example this should work:

po [((UIView*)0x83fcc6d0) accessibilityIdentifier]

However, the technique I prefer to use is to talk Swift:

expr -l Swift -- import UIKit
expr -l Swift -- let $v = unsafeBitCast(0x83fcc6d0, to: UIView.self)
expr -l Swift -- print($v.accessibilityIdentifier)
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • You can in general use property notation. You might have to provide type casting for property of a property (self.view.superview or the like) if we don't have the full definitions of the properties (which live in the implementing file.) – Jim Ingham Apr 08 '19 at 19:42
  • @JimIngham You're the expert (so I'm glad you're here). All I know is that I could reproduce his results and couldn't solve it in any way when using property notation, but was able to solve it by switching to method notation. – matt Apr 08 '19 at 19:47
0

Stopped in the viewDidLoad of a ViewController, you can access the "view" property just as you would in code:

(lldb) expr self.view
(UIView *) $0 = 0x0000000100615150

Now we have the address of a UIView, let's try accessing its properties:

(lldb) expr ((UIView *) 0x0000000100615150).frame
(CGRect) $5 = (origin = (x = 0, y = 0), size = (width = 768, height = 1024))

The property vrs. method notation "should" just be an automatic substitution in the compiler. However, when we don't know the type of the property, using property access in the debugger's expression parser can run into trouble, especially when you chain properties.

The reason for this is that it is actually unsafe (can corrupt the stack of the debugee) if lldb calls a struct returning function (like UIView's "frame" property) using the scalar calling convention. So lldb is extra careful that it knows the types of the elements in an expression before calling it. If lldb can't figure it out from debug info, it may require extra casting to make the type checker happy.

Note, lldb makes one exception to the requirement that we know the types in expressions which may account for the differences you mentioned. If we see:

[<some expression whose type we don't know> someSelector]

as an expression or sub-expression, we will rewrite this as:

[(id) <some expression whose type we don't know> someSelector]

That seemed a reasonable assist, since the only thing it makes sense to send an ObjC message to is an "id". So any mistake will be a nonsensical one and so hopefully less likely. That does mean a chain of method accesses that all return "id" will get resolved when the equivalent . form would fail the type checker.

This is all the messy corners of dealing with incomplete type information at debug time. Note, many of these issues are resolved by either building your program using modules (-fmodule and -gmodule) or equivalently by issuing:

(lldb) expression @import UIKit

as part of your debug session. Then lldb will know all the types from UIKit, and the expression parser can do a better job.

Jim Ingham
  • 25,260
  • 2
  • 55
  • 63