在 Xcode 中对子类使用符号断点?

Posted

技术标签:

【中文标题】在 Xcode 中对子类使用符号断点?【英文标题】:Using of symbolic breakpoints for child classes in Xcode? 【发布时间】:2015-07-14 10:11:58 【问题描述】:

我有一个类 SomeClass,它继承自 UIView,我想跟踪它的方法 setFrame: 的调用位置。

UIView 的情况下,我可以添加一个值为-[UIView setFrame:] 的符号断点,但我不能为我自己的类做同样的事情——它根本不会在断点上调用/停止。当然我不能使用-[UIView setFrame:],因为它会被额外调用。如何解决这个问题?

我可以在我自己的类中覆盖setFrame:,但在这种情况下我不需要符号断点,最好使用通常的断点。但是在这种情况下,我还需要在自己的类中添加一些更改,这对我来说不是很合适。

【问题讨论】:

如果你使用Xcode设置断点(即点击方法左侧的gutter)呢? facepalm 每次调用这个方法都必须点击左边吗? 你傻吗?我已经写过我可以做到,但我不想在项目中查看每个调用,因为它们的数量 我不明白这里发生了什么;我以为我已经回复了您的第二条评论,但我再也看不到它了。我也不明白你为什么要问我是不是傻。 一般来说,我描述了一个很难完全手动执行的任务,并询问如何至少部分地自动化它。然后你“建议”我在一个问题中描述的完全手动的方式。我该如何应对? 【参考方案1】:

如果我理解正确,您想在 -[UIView setFrame:] 上放置一个断点,但只有在“self”是 SomeClass 类的对象时才停止。您可以使用断点条件来做到这一点。比如:

(int) strcmp("SomeClass", (const char *)class_getName((id)[(id) $arg1 class])) == 0

这里唯一的技巧是$arg1 是保存第一个参数的寄存器的别名,并且在ObjC 方法中第一个参数总是self。注意,$arg1 寄存器别名仅为使用寄存器传递参数的架构定义;特别是 32 位 x86 不会以这种方式传递参数。以下答案很好地描述了如何获得最常见架构的第一个参数:

Symbolic breakpoint for when dispatch_async is called with a specific queue

这可能会稍微减慢您的进程,因为它会在每次调用 [UIView setFrame] 时停止,但没有好的方法可以避免这种情况,除非您建议覆盖 setFrame: 然后停在那里。

我也有点讨厌这里的演员阵容。我们没有其中许多函数的调试信息,因此您必须告诉调试器它们的返回类型是什么。

顺便说一句,lldb 命令行也有一个“选择器中断”类型,它将中断给定选择器的所有实现。没有 UI 方法可以调用它,但在控制台中你可以这样做:

(lldb) break set -S setFrame:

所以你可以在所有 setFrame: 方法上设置一个断点,然后添加相同的条件(你可以通过将-c 标志传递给break set 命令来做到这一点。如果这个断点最终匹配了太多的函数,您可以通过使用break list 查找其索引来禁用单个命中,然后使用您将在break list 输出中看到的bkpt.loc 表单逐一禁用它们。

【讨论】:

看来你已经完全了解我了。但我得到error: use of undeclared identifier 'self'。也许我还应该做更多的事情? 是的,你不能使用“self”,因为你在没有调试信息的代码中设置了这个断点。我在上面使用了 $arg1,这是第一个参数传递寄存器的 lldb 符号。之所以可行,是因为 self 将作为第一个参数传入,并且当 self 尚未从该寄存器中复制出来时,我将在函数的开头停止。 对不起,我还是不明白怎么用。我得到同样的错误:error: use of undeclared identifier '$arg1'。如何正确使用? 您在调试 32 位 x86 二进制文件吗? 32 位 x86 不使用寄存器进行参数传递,它在堆栈上传递。所以在这种情况下,你应该使用:(id)($esp+4) 而不是 $arg1。这个问题已经在这里讨论过:***.com/questions/30470217/… 差不多。我关注了您的链接并使用了*(id*)($esp+4)。您能否将有关这些各种参数的信息添加到您的答案中?所以我可以批准它作为答案。

以上是关于在 Xcode 中对子类使用符号断点?的主要内容,如果未能解决你的问题,请参考以下文章

想知道如何以编程方式在 swift 3.0 中对 UITableViewCell 进行子类化?

是否可以在 Pyspark 中对 DataFrame 进行子类化?

在 CoreData 中使用 NSManagedObject 子类找不到 xcode8 标头

当我使用 Xcode 编辑器创建 NSManageObject 子类时出现错误?

如何在 Xcode8 中手动触发 NSManagedObject 子类的生成

iOS 符号表恢复 & 逆向支付宝