http://blog.cnbluebox.com/blog/2015/03/05/chisel/

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

相信每个人或多或少都在用LLDB来调试,比如po一个对象。LLDB的是非常强大的,且有内建的,完整的
Python 支持。今天我们主要介绍一个 facebook 开源的 lldb 插件 Chisel。可以让你的调试更Easy.

1.安装Chisel

源码地址: Chisel

Chisel 使用 homebrew 来安装,如果你没有安装homebrew, 参考 homebrew

1
2
brew update
brew install chisel

安装完成按照安装日志上的提示,在~/.lldbinit文件中添加一行,没有则新建。
提示类似如下:

1
2
3
==> Caveats
Add the following line to ~/.lldbinit to load chisel when Xcode launches:
command script import /usr/local/opt/chisel/libexec/fblldb.py

做好上面的步骤,然后重启Xcode就可以尝试下了。

2.内置命令

Chisel 为lldb提供了新增的便捷命令,是非常实用的命令

2.1 pviews

这个命令可以递归打印所有的view,并能标示层级,相当于 UIView 的私有辅助方法 [view
recursiveDescription]
 。 善用使用这个功能会让你在调试定位问题时省去很多麻烦。

使用示例:

1
2
3
4
5
6
7
8
9
(lldb) pviews view
<TestView: 0x18df8070; baseClass = UIControl; frame = (144 9; 126 167); layer = <CALayer: 0x18df8150>>
| <UIView: 0x18df81d0; frame = (0 0; 126 126); userInteractionEnabled = NO; layer = <CALayer: 0x18df8240>>
| <UIImageView: 0x18df8330; frame = (0 0; 126 126); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x18df83b0>>
| <UILabel: 0x18df8460; frame = (0 135; 126 14); text = 'haha'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x18df7fb0>>
| | <_UILabelContentLayer: 0x131a3d50> (layer)
| <UILabel: 0x18df8670; frame = (0 155; 126 12); text = 'hahaha'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x18df8730>>
| | <_UILabelContentLayer: 0x131bea10> (layer)
| <UIImageView: 0x18df88d0; frame = (0 9; 28 27); hidden = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x18df8ba0>>

2.2 pvc

这个命令也是递归打印层级,但是不是view,而是viewController。利用它我们可以对viewController的结构一目了然。 其实苹果在IOS8也默默的添加了 UIViewController 的一个私有辅助方法[UIViewController
_printHierarchy]
 同样的效果。

预览效果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(lldb) pvc
<TabBarController: 0x13772fd0; view = <UILayoutContainerView; 0x151b3a30>; frame = (0, 0; 414, 736)>
| <UINavigationController: 0x1602b800; view = <UILayoutContainerView; 0x1b00aca0>; frame = (0, 0; 414, 736)>
| | <FirstViewController: 0x16029c00; view = <UIView; 0x1b01e1c0>; frame = (0, 0; 414, 736)>
| <UINavigationController: 0x138c5200; view = <UILayoutContainerView; 0x1316a080>; frame = (0, 0; 414, 736)>
| | <SecondViewController: 0x16030400; view = <UIView; 0x2094b370>; frame = (0, 0; 414, 736)>
| | | <SecondChildViewController: 0x15af6000; view = <UIView; 0x18d4e650>; frame = (0, 64; 414, 628)>
| <UINavigationController: 0x1383ca00; view = <UILayoutContainerView; 0x13180070>; frame = (0, 0; 414, 736)>
| | <ThirdViewController: 0x138ddc00; view = <UIView; 0x18df6650>; frame = (0, 0; 414, 736)>
| | | <ThirdChild1ViewController: 0x1393fe00; view = <UIView; 0x131ec000>; frame = (0, 0; 414, 672)>
| | | <ThirdChild2ViewController: 0x138dce00; view = <UIView; 0x204075a0>; frame = (414, 0; 414, 672)>
| | | <ThirdChild3ViewController: 0x138a8e00; view = <UIView; 0x20426250>; frame = (828, 0; 414, 672)>
| <UINavigationController: 0x160eca00; view = <UILayoutContainerView; 0x152f7d90>; frame = (0, 0; 414, 736)>
| | <FourViewController: 0x13157cc0; view not loaded>

是不是方便很多呢,而且还可以看到 viewController 是否已经 viewDidLoad .

2.3 visualize

这是个很有意思的功能,它可以让你使用Mac的预览打开一个 UIImage, CGImageRef, UIView, 或 CALayer。 这个功能或许可以帮我们用来截图、用来定位一个view的具体内容。 但是在我试用了一下,发现暂时还是只能在模拟器时使用,真机还不行。

使用简单:

1
(lldb) visualize imageView

2.4 fv & fvc

fv 和 fvc 这两个命令是用来通过类名搜索当前内存中存在的view和viewController实例的命令,支持正则搜索。

如:

1
2
3
4
5
6
7
8
9
(lldb) fv scrollView
0x18d3b8c0 UIScrollView
0x137d0c50 UIScrollView
0x131b1580 UIScrollView
0x131b2070 UIScrollView
(lldb) fvc Home
0x1393fe00 HomeFeedsViewController
0x138a8e00 HomeFeedsViewController
(lldb)

2.5 show & hide

这两个命令用来显示和隐藏一个指定的 UIView . 你甚至不需要Continue Progress. 就可以看到效果。

2.6 mask/umask border/unborder

这两组命令用来标识一个view或layer的位置时用, mask用来在view上覆盖一个半透明的矩形, border可以给view添加边框。但是在我实际使用的过程中mask总是会报错,估计是有bug, 那么mask/unmask 一般不要用好了,用border命令是一样的效果,反正二者的用途都是找到一个对应的view.

2.7 caflush

这个命令会重新渲染,即可以重新绘制界面, 相当于执行了 [CATransaction flush] 方法,要注意如果在动画过程中执行这个命令,就直接渲染出动画结束的效果。

当你想在调试界面颜色、坐标之类的时候,可以直接在控制台修改属性,然后caflush就可以看到效果啦,是不是要比改代码,然后重新build省事多了呢。

例, 其中 $122 即是目标UIView:

1
2
3
4
(lldb) p view
(long) $122 = 140718754142192
(lldb) e (void)[$122 setBackgroundColor:[UIColor greenColor]]
(lldb) caflush

2.8 bmessage

这个命令就是用来打断点用的了,虽然大家断点可能都喜欢在图形界面里面打,但是考虑一种情况:我们想在 [MyViewController
viewWillAppear:]
 里面打断点,但是 MyViewController并没有实现viewWillAppear: 方法,
以往的作法可能就是在子类中实现下viewWillAppear:,然后打断点,然后rebuild。

那么幸好有了 bmessage命令。我们可以不用这样就可以打这个效果的断点: (lldb)
bmessage -[MyViewController viewWillAppear:] 
上面命令会在其父类的 viewWillAppear: 方法中打断点,并添加上了条件:[self
isKindOfClass:[MyViewController class]]

3. 自定义命令

我们也可以自定义插件,不过前提是要懂一些 python。 比如设计一个打印keyWindow的windowLevel的命令:

创建python脚本文件 /magical/commands/example.py :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/python
# Example file with custom commands, located at /magical/commands/example.py import lldb
import fblldbbase as fb def lldbcommands():
return [ PrintKeyWindowLevel() ] class PrintKeyWindowLevel(fb.FBCommand):
def name(self):
return 'pkeywinlevel' def description(self):
return 'An incredibly contrived command that prints the window level of the key window.' def run(self, arguments, options):
# It's a good habit to explicitly cast the type of all return
# values and arguments. LLDB can't always find them on its own.
lldb.debugger.HandleCommand('p (CGFloat)[(id)[(id)[UIApplication sharedApplication] keyWindow] windowLevel]')

其中定义了PrintKeyWindowLevel的类,需要实现 name description run 方法来分别告诉名称、描述、和执行实体。

创建好脚本后,然后在前面安装时创建的 ~/.lldbinit文件中添加一行:

1
script fblldb.loadCommandsInDirectory('/magical/commands/')

然后重启Xcode之后就可以使用自定义的命令啦。

参考文献:

Chisel官方说明

与调试器共舞 – LLDB 的华尔兹

Chisel-LLDB命令插件,让调试更Easy的更多相关文章

  1. [转]九个Console命令,让js调试更简单

    转自:九个Console命令,让js调试更简单 一.显示信息的命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <!DOCTYPE html> <html ...

  2. IOS调试lldb命令常用,po,

    lldb命令常用(备忘) 假如你准备在模拟器里面运行这个,你可以在"(lldb)"提示的后面输入下面的: (lldb) po $eax LLDB在xcode4.3或者之后的版本里面 ...

  3. IOS调试lldb命令常用po

    lldb命令常用(备忘) 假如你准备在模拟器里面运行这个,你可以在“(lldb)”提示的后面输入下面的: (lldb) po $eax LLDB在xcode4.3或者之后的版本里面是默认的调试器.假如 ...

  4. 【F12】Console命令,让js调试更简单

    Console命令,让js调试更简单 一.显示信息的命令 console.log("normal"); // 用于输出普通信息 console.info("informa ...

  5. Chisel常用命令总结

    Chisel简介 Chisel是Facebook开源的一款lldb调试工具,其实就是对系统lldb命令的封装,开发者可以通过简化的命令更方便的进行调试工作.开源地址:https://github.co ...

  6. Chisel辅助iOS 应用程序调试,MusicApp模仿酷狗4.0 UI框架

    本文转载至 http://www.cocoachina.com/ios/20140825/9446.html Chisel Chisel集合了大量的LLDB 命令来辅助iOS 应用程序调试,并支持添 ...

  7. vue—你必须知道的 js数据类型 前端学习 CSS 居中 事件委托和this 让js调试更简单—console AMD && CMD 模式识别课程笔记(一) web攻击 web安全之XSS JSONP && CORS css 定位 react小结

    vue—你必须知道的   目录 更多总结 猛戳这里 属性与方法 语法 计算属性 特殊属性 vue 样式绑定 vue事件处理器 表单控件绑定 父子组件通信 过渡效果 vue经验总结 javascript ...

  8. 分享几个日常调试方法让js调试更简单

    下面分享几个日常调试代码的时候在Console命令行显示你的操作,让你的js调试更简单. console显示信息的命令 在浏览器按f12在console上显示你的文本. <!DOCTYPE ht ...

  9. 让js调试更简单—console

    一.显示信息的命令 console.log 用于输出普通信息 console.info 用于输出提示性信息 console.error用于输出错误信息 console.warn用于输出警示信息 最常用 ...

随机推荐

  1. 清北学堂-DAY2-数论专题-中国剩余定理(CRT)

    首先请看定义:(百科上抄下来的)孙子定理是中国古代求解一次同余式组(见同余)的方法.是数论中一个重要定理.又称中国余数定理. 一元线性同余方程组问题最早可见于中国南北朝时期(公元5世纪)的数学著作&l ...

  2. 通过Nginx统计网站的PV、UV、IP

    转载:通过Nginx统计网站的PV.UV.IP 概念 UV:独立访客:以cookie为依据,假设一台电脑装有3个不同的浏览器,分别打开同一个页面,将会产生3个UV.PV:访问量:页面每访问或刷新一次, ...

  3. 二零一八阿里p7笔试116题

    1. junit用法,before,beforeClass,after, afterClass的执行顺序 2. 分布式锁 3. nginx的请求转发算法,如何配置根据权重转发 4. 用hashmap实 ...

  4. Flutter——AppBar组件(顶部导航组件)

    AppBar组件的常用属性如下: 属性 描述 leading 在标题前面显示的一个控件,在首页通常显示应用的 logo:在其他界面通常显示为返回按钮 title 标题,通常显示为当前界面的标题文字,可 ...

  5. 怎奈风云多变换,骚完一波还一波,记PHP mongodb驱动的2019年11月用法

    怎么,觉得pecl下一个扩展包,phpize make make install  php.ini里引用一下 mongodb.so就万事大吉了? Deeply Sorry!看到MongoDB\Driv ...

  6. Java8-Lambda-No.05

    import java.util.HashMap; import java.util.function.BiConsumer; public class Lambda5 { //Pre-Defined ...

  7. Time travel HDU - 4418 (概率DP)

    对于每个点两个方向(两头只有一个方向)建一个点,然后预处理出每个点走k(1≤k≤n)k(1\le k\le n)k(1≤k≤n)到哪个点,列出方程式高斯消元就行了.记得前面bfsbfsbfs出那些点不 ...

  8. 自定义错误throw

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. mapbox-gl空间分析插件turf.js使用介绍

    mapbox-gl能够方便地显示地图,做一些交互,但是缺少空间分析功能,比如绘制缓冲区.判断点和面相交等等. turf.js是一个丰富的用于浏览器和node.js空间分析库,官网 http://tur ...

  10. Jekyll添加FancyBox 插件

    一.简要 这是之前在GitHub Page上面使用博客功能的完善,之前每次传到GitHub上面的图片在博客里面都是显示压缩后的,导致很多代码细节都看不清. Markdown 语法中的图片我们一般是如此 ...