Chisel-xcode 下的调试神器

LLDB 是一个有着 REPL 的特性和 C++ ,Python 插件的开源调试器。LLDB 绑定在 Xcode 内部,存在于主窗口底部的控制台中。调试器允许你在程序运行的特定时暂停它,你可以查看变量的值,执行自定的指令,并且按照你所认为合适的步骤来操作程序的进展。

安装

1、brew update

2、brew install chisel

3、touch ~/.lldbinit,创建文件 .lldbinit,并将下面内容复制到文件中,保存退出。

command script import /usr/local/opt/chisel/libexec/fblldb.py

4、 重启xcode,插件即可生效

使用

Chisel是一个 facebook 开源的 lldb 插件,为lldb提供了新增的便捷命令,能够帮助快速 debug,是非常实用的命令。

为了跟踪demo UI与底层源码的关联,借助该插件中的强大的指令集可以帮助我们快速了解新接触的 demo。

首先,xcode 控制台输入”help” ,可以看到当前可用的一些指令集。如下图所示:



在平时的测试工作中,当拿到一个新的工程,面对demo 的各种控件,要查看当前控件对象的类的继承关系,可以通过pclass来查看,比如UIViewController处设置断点,呼出lldb控制台,然后再这里输入pclass这个命令,其中参数0x10400ba00为 tableView 对象的地址。如下图所示:



接下来,针对每个对象,使用pviews命令的输出中可以查看控件的属性,根据属性可以初步查看当前控件的位置及大小。如下图所示:




对于 demo 引用的到素材,visualize命令,可以使用mac下的预览app打开我们demo的图片UIImage, CGImageRef格式的图片,甚至view和layer的图片 ,如图所示:


当然,在测试 demo 的功能逻辑实现时是否正确时,简单的 UI层面还不够,需要深入到底层,了解每个对象的职责。pinternal可以查看一个控件类型的内部结构,包括自定义的控件的类型,比如查看控件 tableView 的内部结构,如下图所示:



除了需要对对象有一个纵向的认识外,要了解到对象之间的横向关系,使用presponder指令,如图五所示,列出了集成于tableView控件的消息传递链,方便我们查看消息是如何传递的。



这里只对常用的几个封装的命令进行了举例说明,其他常用的命令还有很多(详情见文末),都是使用python封装了一下函数然后调用的。凡是这些封装的命令,你都可以通过多个lldb命令打出来,Chisel插件帮我们集成了一些常用的指令集,如果你会使用python的话,那么你可以根据自己的使用习惯封装一些常用的lldb命令。


其他常用命令参考

Print

在LLDB中,我们执行的最多的可能就是打印操作了,chisel专门为这类操作封装了一些打印命令。

1、pviews 递归打印所有的view,并能标示层级

2、pvc 递归打印层级viewController

3、ptv 打印屏幕中显示的tableView,主要是与pcells联合使用。如果有多个tableView,打印View层级中

最上面的一个。

4、pcells 打印tableView中当前可见的cell,如果有多个tableView,打印View层级中最上面的tableView

的可见cell。

5、pdata 对编码过的NSData进行解码打印,等效于调用-[NSString initWithData:encoding:]

6、po 以对象的方式打印结果

Find

1、fvc 根据类名搜索内存中与之匹配的 view

usage:Syntax: fvc [–name=classNameRegex] [–view=view]

–name/-n: string类型参数,根据viewController的Class名字查找viewController

–view/-v: UIView类型参数,根据viewController拥有的view查找viewController

Note:上面2个option不能同时使用,只能使用某一

2、fv 通过类名搜索当前内存中存在的viewController实例的命令,支持正则搜索。

3、taplog 将点击的view打印出来,这个命令对于查找哪个view非常有帮助。

usage:我们需要先将程序暂停,输入taplog,程序会自己运行,这时候点击你需要查看的view,控制台上就会显示出你刚刚点击的view相关信息。

Note:要查看的view必须能接收点击事件,也就是他的userInteractionEnabled必须为YES才能被找到,UILabel和UIImageView默认userInteractionEnabled为NO。

4、vs 在view层级中搜索view,并显示出来

Note:相比fv,vs主要用于显示view在屏幕上的位置

Display

1、caflush 一般我们用LLDB命令改变UI,UI并不会立即更新,我们需要使用caflush刷新界面

2、border 给View或者layer加上border

usage:

Syntax: border [–color=color] [–width=width]

<viewOrLayer>

–color/-c: 边框颜色,string类型

–width/-w: 边框宽度

<viewOrLayer>: 需要设置边框的view或者layer

3、mask 给view添加一个半透明的矩形mask,用来查看view的位置

usage:Syntax: mask [–color=color] [–alpha=alpha] <viewOrLayer>

–color/-c: mask的颜色,string类型

–alpha/-a: mask的透明度

<viewOrLayer>: 需要添加mask的view或者layer

4、show 显示一个view或者layer,相当于执行

view.hidden = NO

Preview

1、visualize 用预览App打开UIImage, CGImageRef, UIView, CALayer等对象

usage:

Syntax: visualize <target>

<target>: 需要预览的对象,id类型

Debug

1、bmessage 在类方法或实例方法中设置符号断点,而且不用担心层次结构中具体是哪个类实现了该方法。

usage:Syntax: bmessage <expression>

<expression>: 设置断点的方法名

2、wivar 在对象的实例上设置观察点(watchpoint)

usage:

Syntax: wivar <object> <ivarName>

<object>: 需要为成员变量设置watchpoint的对象。id类型

<ivarName>: 成员变量的名字,注意一般属性对应的成员变量带有_前缀

Autolayout

autolayout中有一种bug叫Ambiguous Layouts,意思是你设置的约束不足以确定view的位置或大小。比如你只设置了X轴的位置,没有设置Y轴的位置。

autolayout提供了专门判断和查找这类问题的方法:

1、hasAmbiguousLayout用于判断是否存在Ambiguous Layouts

2、_autolayoutTrace用于查找存在的Ambiguous Layouts

alamborder

即使有上述查找的方法,真正去做这个事儿也比较费时费力的, alamborder给存在Ambiguous Layouts的view加上border,方便查找哪些View存在问题。

usage:

Syntax: alamborder [–color=color] [–width=width]

1、–color/-c: border的颜色,参数为string类型,比如’red’, ‘green’, ‘magenta’等,不设置默认为红色。

–width/-w: border的宽度,参数为CGFloat类型,不设置默认宽度为2。

alamunborder

去掉alamborder设置的border。

usage:Syntax: alamunborder

e.g: 针对上面设置的border,在lldb控制台输入alamunborder即可去掉边框。

paltrace

打印某个View的autolayout详细信息,相当于调用_autolayoutTrace

usage:Syntax: paltrace <view>

其中<view>: 需要打印详细信息的view,不传参数默认为keyWindow。

eg: 查看一下keyWindow上有哪个view存在Ambiguous Layouts。

这篇文章是为了想你展示 LLDB 中Chisel插件的强大之处,鼓励我们避开繁琐的 NSlog, 尝试并探索在控制台使用命令的便捷性。

当然Chisel的命令很多,在这里只对常用的一些命令进行了总结,若有其他需求,请大家移至Chisel参考文档:GitHub - facebook/chisel: Chisel is a collection of LLDB commands to assist debugging iOS apps.

Q


本文转载自 360质量效能