ios调试技巧(3 )设置符号断点

975 阅读4分钟

今天我要写的是 LLDB 的高级调试特性。我称它为高级是因为我自己很长时间都不知道它。它允许您添加一个符号断点,该断点将在特定点停止执行,以便您可以回溯并开始调查触发此方法调用的位置。

如果上面的介绍没让你明白,让我用一个例子解释一下。假设在您的代码中的某个地方,调用了一个关闭 UIViewController 的方法 dismissViewController。现在你的代码库中可能有数百个dismissViewController 方法。但是你怎么知道代码的哪一部分实际调用了这个dismissViewController方法呢?这个问题的答案是添加符号断点。

一旦你在dismissViewController 方法处添加一个符号断点进行中断,程序执行将在它处停止,并在堆栈跟踪中返回将让你找到导致controller 被dismiss的原因。

Screen-Shot-2019-06-12-at-11.28.19-PM.png

参考上面的截图,我们的程序流程已经在dismissViewController的调用处中断。如果我们追溯它,我们知道类 Sample 中的 viewDidAppear 方法负责关闭这个视图控制器。

让我们看一下可以在程序执行期间添加的不同符号断点的示例,

1.给对象属性值设置值时的符号断点

例如,您有一个 UILabel 或 UITextView 对象,并且您想知道某些属性(例如 text、numberOfLines 或 translatesAutoresizingMaskIntoConstraints)分配给它们的位置。您可以单击 Breakpoint Navigator 并单击底部的 + 符号,然后选择 Symbolic Breakpoint 作为选项。

Screen-Shot-2019-06-13-at-7.43.50-AM.png

Screen-Shot-2019-06-13-at-7.43.58-AM.png

现在,根据您想要break at 的condition,您可以在“符号”字段旁边添加以下值

Snip20220914_1.png

现在,您可能会这样问, 这对于简单变量的放一个断点很好处理。但是,当属性名称是 isScrollEnabled 或 isEditable 呢?

幸运的是,它与我们之前所做的非常相似。您需要做的就是去掉前缀 is,然后和之前相同的处理逻辑。

Snip20220914_2.png

2.  Symbolic breakpoint when UIViewController is presented

当项目中的任意位置准备present视图控制器时你想断点程序,您可以通过将以下符号添加到符号断点来实现


-[UIViewController presentViewController:animated:completion:]

  1. Symbolic breakpoint when UIViewController is dismissed

When UIViewController is dismissed, it can be caught by adding the following symbol

-[UIViewController dismissViewControllerAnimated:completion:]

  1. Symbolic breakpoint when UIViewController is pushed on the navigation stack

相似的符号当 UIViewController  instance 被push在导航控制器


-[UINavigationController pushViewController:animated:]

  1. Symbolic breakpoint when you UIViewController is popped from the navigation stack

And when current UIViewController instance is popped from the navigation stack


-[UINavigationController popViewControllerAnimated:]

  1. Symbolic breakpoint when UIViewController's lifecycle methods are called

This is a one-off trick to catch execution of any of the lifecycle methods associated with UIViewController such as viewDidLoad, viewDidAppear, viewWillAppear and so on. For example, you can stop the execution when the viewDidLoad method gets called using the following symbol,


-[UIViewController viewDidLoad]

##符号断点使用需要注意的点:

1.符号断点和普通断点的最大区别是:如果你想断点的地方是系统的framework或者第三方的你没办法拿到源码的framework情况,你都需要符号断点,因为普通断点你必须到 .m文件中去才行

2.特别需要的符号断点的写法:

    对于  -[UINavigationController pushViewController:animated:] 来说你可以有两种写法: a. 就按照上面的这种写法写,但是需要注意的注意点是 - 和 [ 之间不能留空格,否则断点无效。类名UINavigationController 和pushViewController:animated: 之间必须加空格 

如果方法中有参数,比方说 pushViewController:, 特别需要注意的是 pushViewController: 后面要紧跟着animated:  , ```:````后面不能加空格。

    b.还可以直接 写 ``` pushViewController:animated: ````会将所有有这个符号的类都加上断点

    

3.- [类名 方法名] ,这个方法必须要自己实现的才行,如果是继承过来的,断点无效。比方说你设置了一个 LWZTestLabel 方法,但是你使用 -[LWZTestLabel  setHidden]方法,因为这个方法是UIView 的方法,所以你这样设置符号断点并没效果。

4.断点的条件表达式Condition如何书写?

i > 5000

i == 99

(BOOL)[item isEqualToString:@"three”],前面的(BOOL)是必须的,否则console会提示类型不符号,导致条件不能生效。

  1. objc_msgSend(id self, SEL selector, parmat1, parmat2)

所以不论在哪个方法停留我们都可以拿到获取 arg1(就是当前方法的调用者self)arg1 (就是当前方法的调用者 self), arg2 就是selector,可以根据这些参数做一些条件判断或者输出。