我有一个UIViews树,我试图理解:UIPageViewController高度是一个状态栏高度太高,不知何故底部是foobar在层次结构的某个地方下降到窗口房地产高度明智。这是我与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'
po
。所以例如这应该工作:
po [((UIView*)0x83fcc6d0) accessibilityIdentifier]
但是,我喜欢使用的技术是谈Swift:
expr -l Swift -- import UIKit
expr -l Swift -- let $v = unsafeBitCast(0x83fcc6d0, to: UIView.self)
expr -l Swift -- print($v.accessibilityIdentifier)
停在ViewController的viewDidLoad中,您可以像在代码中一样访问“view”属性:
(lldb) expr self.view
(UIView *) $0 = 0x0000000100615150
现在我们有了一个UIView的地址,让我们尝试访问它的属性:
(lldb) expr ((UIView *) 0x0000000100615150).frame
(CGRect) $5 = (origin = (x = 0, y = 0), size = (width = 768, height = 1024))
物业vrs。方法表示法“应该”只是编译器中的自动替换。但是,当我们不知道属性的类型时,在调试器的表达式解析器中使用属性访问可能会遇到麻烦,尤其是在链接属性时。
这样做的原因是,如果lldb使用标量调用约定调用结构返回函数(如UIView的“frame”属性),它实际上是不安全的(可以破坏debugee的堆栈)。所以lldb要特别小心,它在调用之前知道表达式中元素的类型。如果lldb无法从调试信息中找出它,则可能需要额外的转换才能使类型检查器满意。
注意,lldb对我们知道表达式中可能解释您提到的差异的类型的要求提出了一个例外。如果我们看到:
[<some expression whose type we don't know> someSelector]
作为表达式或子表达式,我们将其重写为:
[(id) <some expression whose type we don't know> someSelector]
这似乎是一个合理的帮助,因为发送ObjC消息唯一有意义的是“id”。所以任何错误都将是一个荒谬的错误,所以希望不太可能。这确实意味着所有返回“id”的方法访问链将在等效时得到解析。表单将失败类型检查器。
这是在调试时处理不完整类型信息的所有混乱角落。注意,许多这些问题都可以通过使用模块(-fmodule
和-gmodule
)构建程序或通过发出以下方式来解决:
(lldb)表达式@import UIKit
作为调试会话的一部分。然后lldb会知道UIKit中的所有类型,表达式解析器可以做得更好。