调试工具Chisel-LLDB插件
2015-11-12 15:42
225 查看
Chisel-LLDB命令插件
相信每个人或多或少都在用LLDB来调试,比如po一个对象。LLDB的是非常强大的,且有内建的,完整的 Python 支持。今天我们主要介绍一个 facebook 开源的 lldb 插件 Chisel。可以让你的调试更Easy.
1.安装Chisel
源码地址: ChiselChisel 使用 homebrew 来安装,如果你没有安装homebrew, 参考 homebrew。
1 2 | brew update brew install chisel |
~/.lldbinit文件中添加一行,没有则新建。 提示类似如下:
1 23 | ==> Caveats Add the following line to ~/.lldbinit to load chisel when Xcode launches: command script import /usr/local/opt/chisel/libexec/fblldb.py |
2.内置命令
Chisel 为lldb提供了新增的便捷命令,是非常实用的命令2.1 pviews
这个命令可以递归打印所有的view,并能标示层级,相当于 UIView 的私有辅助方法[view recursiveDescription]。 善用使用这个功能会让你在调试定位问题时省去很多麻烦。
使用示例:
1 23 | (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 23 | (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> |
2.3 visualize
这是个很有意思的功能,它可以让你使用Mac的预览打开一个 UIImage, CGImageRef, UIView, 或 CALayer。 这个功能或许可以帮我们用来截图、用来定位一个view的具体内容。 但是在我试用了一下,发现暂时还是只能在模拟器时使用,真机还不行。使用简单:
1 | (lldb) visualize imageView |
2.4 fv & fvc
fv和
fvc这两个命令是用来通过类名搜索当前内存中存在的view和viewController实例的命令,支持正则搜索。
如:
1 23 | (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 23 | (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 23 | #!/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/') |
参考文档:http://blog.cnbluebox.com/blog/2015/03/05/chisel/
相关文章推荐
- 访问与评价
- 从运营事故中成长
- 实战阿里云-路由模式工作并端口转发(端口映射)
- 用牛顿迭代法求根
- Error creating bean with name 'org.springframework.validation.beanvalidation.LocalValidatorFactoryBe
- android中普通的java对象转换成 json格式的字符串
- Hello world!
- 朴素贝叶斯
- XAMPP安装注意事项之apache
- 使用uiautomator时遇到问题的处理方法
- lintcode 中等题:Longest Palindromic Substring 最长回文子串
- URI和URL的区别
- [并发并行]_[Object-C]_[使用NSMutableArray等非线程安全集合类的注意事项]
- Java程序员到架构师的推荐阅读书籍
- CHM文件打开 右边内容是空白
- PHP颜色随机生成器
- [并发并行]_[Object-C]_[使用NSMutableArray等非线程安全集合类的注意事项]
- 决策树ID3
- 第一章:SolrCloud4.9+zookeeper在CentOS上的搭建与安装
- vmware fusion8虚拟机win10桥接无法上网的问题