【老司机精选】通过断点技巧让调试更高效

作者:PerTerbin,上任于字节跳动抖音直播团队。

审阅:孙磊,iOS开发,字节跳动资深工程师

本文根据 WWDC21 Session 10209 整理。

前语

断点关于每个开发者都不生疏,它是咱们工作中极其重要的东西。经过断点调试,咱们能够在程序运转期间中止程序,并检查程序的各种状况来解决遇到的问题。本文咱们将介绍 Xcode 中止点调试的技巧及 WWDC21 中苹果关于断点提出的新技能,学会这些技巧关于开发者来说都十分有必要,它能使咱们的工作愈加高效。

文章首要讨论下列三种常见的断点:

  • 源文件断点(Source File Breakpoints)
  • 符号断点(Symbolic Breakpoints)
  • 运转时问题断点(Runtime Issue Breakpoints)

源文件断点

源文件断点顾名思义便是在单个文件上设置的断点,最常见的便是单行断点。单行断点是咱们开发顶用的最多的断点,设置单行断点也十分简单,只需求咱们在需求中止的代码行边上单击即可。

【老司机精选】通过断点技巧让调试更高效

设置单行断点后,当程序运转到该行代码时,程序会中止,一起 Xcode 底部的控制台支撑咱们运用 LLDB 对程序进行调试。在 LLDB 中咱们能够经过 p 或者 po 指令打印出咱们关心的变量,控制台会输出对应变量实时的值,这对咱们检查程序状况是否契合预期十分有用。

【老司机精选】通过断点技巧让调试更高效

一起咱们能够经过 expression 指令(简写 e 或 expr)在 LLDB 中履行语句,根据此咱们能够在断点里实时修正程序的各种状况而不需求从头编译程序,毕竟从头编译对大型 App 来说是致命的。比方下图的比方,咱们能够实时修正 isDarkMode 变量的值,从而让程序走另一个条件分支。

【老司机精选】通过断点技巧让调试更高效

除了修正一般变量外,咱们也能够运用 expression 修正 UI 内容,比方下方比方咱们能够动态修正 testView 的透明度。

【老司机精选】通过断点技巧让调试更高效

运用 expression 修正透明度后会发现 App 样式没有改写,那是因为在断点中止状况下,咱们仅仅修正了值,并没有对屏幕进行改写。这时候咱们能够经过以下指令来改写界面。

expression [CATransaction flush]

上述指令履行后,你会发现 App 界面呈现了令人振奋的一幕。

【老司机精选】通过断点技巧让调试更高效

除了在程序中止时经过 LLDB 调试器修正 App 状况,还能够经过在断点中增加 Action 来完成同样的功用,经过断点来设置调试指令的办法愈加便利有用,几乎是实时插入代码的作用。如下图,在代码完毕前设置一个断点,在编辑框填入多个不同的调试指令,就能完成实时修正代码的作用。一起能够勾选 Automatically continue after evaluationg actions,勾选后程序运转到该断点时只会运转相应的指令而不会中止程序,这样就能够在不从头编译的状况下实时注入代码,这对大型 App 来说几乎便是救星,毕竟大型 App 一编译便是一杯咖啡的时刻。

【老司机精选】通过断点技巧让调试更高效

单行断点在大部分状况下已经能满意咱们的日常需求,可是在某些毕竟杂乱的场景下运用起来仍是比较费事,比方下方代码:

	BPDIManager *manager = [BPDIManager aDIManagerForContent:@"globel"];
  id object = [manager objectWithProtocol:[self protocolWithType:self.type]];

假定咱们要经过断点调试 objectWithProtocol 办法是否契合预期,咱们能够在这行设置单行断点,但因为程序的运转顺序,当咱们 Step Into 单步调试走进去时,会发现咱们进去的是 protocolWithType 办法,当然咱们能够履行完这个办法后经过 Step Out 退出该办法,然后再 Step Into 就能进入咱们要调试的办法,可是假如咱们需求屡次调试这个办法,这就显得很费时,适当影响咱们的调试功率

在 Xcode 13,苹果新引入了列断点(Column Breakpoint)。列断点支撑咱们在某一行的某一个表达式设置断点,当设置列断点后,程序会在履行列断点设置的表达式之前中止。咱们能够经过 Command + 单击需求设置断点的办法,然后在 Xcode 弹起的选择框里选择 Set column breakpoint 来设置列断点。设置列断点后,Xcode 会在办法上方显现一个标识断点的 icon,咱们能够像单行断点相同单击 icon 来开关断点,一起双击断点后相同能够编辑断点。设置列断点后,程序将在设置断点的办法之前中止,比方下方断点将在 objectWithProtocol 调用之前中止,其他办法不会触发断点。

【老司机精选】通过断点技巧让调试更高效

Xcode 11.4 之后引入了 line PC,Xcode 会在下一步要履行的表达式下发增加一条绿色的高亮线,开发者能更直观的了解下程序的运转状况。

【老司机精选】通过断点技巧让调试更高效

列断点关于Objective-C 的 block 和 Swift 的闭包来说几乎便是神器。比方下面 Swift 代码要调试最终一个 0,经过单行断点调试是适当费事的,咱们没办法直观的看到最终一个0,经过单行断点调试是适当费事的,咱们没办法直观的看到最终一个 0 的值。

【老司机精选】通过断点技巧让调试更高效

有了列断点,这种状况咱们能轻松解决,今后开发者中遇到比较杂乱的单行代码也能很便利的调试,不得不说,苹果这个更新适当有用。

【老司机精选】通过断点技巧让调试更高效

符号断点

符号断点可经过设置函数称号来增加断点,LLDB 会匹配进程中加载的一切库(包括系统库)中的函数称号,假如程序运转到对应的函数将会产生中止。符号断点在平时开发中适当有用,特别是关于一些没有源码权限的库,包括三方库和系统库。在 Xcode 断点栏点击左下角 + 号能够增加符号断点。

【老司机精选】通过断点技巧让调试更高效

比方咱们增加一个名为 setAlpha: 的符号断点,会发现筛选出一切契合条件的断点。

【老司机精选】通过断点技巧让调试更高效

假如咱们只对某几个断点感兴趣,咱们能够经过指定 Module 让符号断点只在某个库中收效,这样就能有效的限制符号断点的数量。

【老司机精选】通过断点技巧让调试更高效

符号断点经常在没有源码权限的库中运用,因为关于源码权限,所以咱们只能看到汇编代码。关于汇编代码,咱们能够经过 LLDB 读取寄存器内容来查验办法入参是否契合预期,register read 指令能够检查一切寄存器内容。

【老司机精选】通过断点技巧让调试更高效

上图能够看到一切寄存器,可是寄存器称号不好记,咱们也能够运用 $arg1$arg2 等符号来检查办法入参。如下图,$arg1是办法第一个参数也便是对象自身,$arg2是办法第二个参数也便是 SEL,po 指令无法直接输出函数名,需求加上(SEL)强转,$arg3是被赋给text的值。

【老司机精选】通过断点技巧让调试更高效

因为符号断点是强匹配开发者输入的符号,所以当开发者设置符号断点后 LLDB 或许会搜索不到,在 Xcode 13中,苹果关于搜索不到的符号断点做了进一步的优化。如下图当咱们输入一个名为 convertToMass 的断点。

【老司机精选】通过断点技巧让调试更高效

因为程序后没有契合的符号,所以该符号断点没有解析到。关于这种断点,Xcode 13 用了一个新的图标来标识,一起当鼠标移上去后会呈现断点未被解析的或许原因,首要包括三种原因:

  • 符号称号输入错误
  • 一切库均不存在该符号
  • 符号对应的库还没有被加载

前两种原因好理解,第三个原因在这种场景下会呈现:比方你的 App 在某个机遇下(比方点击某个按钮)会加载某个库,这种状况下在未加载时符号断点是不收效的,当库被加载后断点也会被自动解析,一起相应图标也会变成可用状况。经过不同状况的图标标识断点的可用状况,愈加一目了然。

运转时问题断点

运转时问题断点是指能够为运转时呈现的问题设置断点。常见的运转时问题有:

  • 在子线程履行 UI
  • 在非线程安全环境里修正变量
  • 不安全的拜访内存地址
  • 履行会导致不确定行为的代码

呈现运转时问题 Xcode 会在 issue 栏目下展现对应的问题,如下:

【老司机精选】通过断点技巧让调试更高效

运转时呈现上述问题或许会影响 App 的运转状况,严峻的或许会导致程序溃散。针对运转时问题,Xcode 支撑探测器(sanitizers)东西去检测,当敞开探测器后,在调试阶段假如遇到运转时问题,Xcode 会记录到产生问题的代码,并以断点的形式中止,让开发者能更便捷的定位到产生问题的原因。

增加运转时问题断点的办法和增加一般全局断点相同,在断点类型里选择 Runtime Issue Breakpoint

【老司机精选】通过断点技巧让调试更高效

增加断点需求指定相应的运转时问题类型

【老司机精选】通过断点技巧让调试更高效

一起需求在 Scheme Editor 中敞开对应的才能,比方增加子线程改写 UI 检测断点需求敞开 Main Thread Checker,敞开后当程序在运转时检测到相应问题 Xcode 将会以断点形式中止。

【老司机精选】通过断点技巧让调试更高效

总结

断点调试对开发者而言是适当重要的,掌握好断点调试的技巧能使咱们在工作中愈加高效的处理问题。本文介绍了在平时开发中常用的调试技巧,一起介绍了苹果在 WWDC21 提出的关于断点的改进,包括列断点和未解析的断点,其实列断点功用适当强壮,解决了单行杂乱代码不好调试的问题,信任今后列断点会是开发者最常用的调试手法之一。

重视咱们

咱们是「老司机技能周报」,一个持续追求精品 iOS 内容的技能大众号。欢迎重视。

重视有礼,重视【老司机技能周报】,回复「2021」,收取 2017/2018/2019/2020 内参

支撑作者

在这里给我们引荐一下 《WWDC21 内参》 这个专栏,一共有 102 篇关于 WWDC21 的内容,本文的内容也来源于此。假如对其他内容感兴趣,欢迎戳链接阅读更多 ~

WWDC 内参 系列是由老司机牵头安排的精品原创内容系列。 已经做了几年了,口碑一直不错。 首要是针对每年的 WWDC 的内容,做一次精选,并号召一群一线互联网的 iOS 开发者,结合自己的实践开发经历、苹果文档和视频内容做二次创作。