Chisel介绍
安装
在终端输入命令
brew update
brew install chisel
如果没有安装brew的话,会报出-bash: brew: command not found
错误,需要先安装brew
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
然后参照终端上输出的
Add the following line to ~/.lldbinit to load chisel when Xcode launches:
command script import /usr/local/opt/chisel/libexec/fblldb.py
将command script import /usr/local/opt/chisel/libexec/fblldb.py
添加到~/.lldbinit中(如果没有使用命令touch ~/.lldbinit
创建),然后重启Xcode才能使用chisel。
重启Xcode后,通过help命令可以看到多出了很多新的命令,就是chisel中的
Current user-defined commands:
alamborder -- For more information run 'help alamborder'
alamunborder -- For more information run 'help alamunborder'
binside -- For more information run 'help binside'
bmessage -- For more information run 'help bmessage'
border -- For more information run 'help border'
caflush -- For more information run 'help caflush'
dcomponents -- For more information run 'help dcomponents'
eobjc -- For more information run 'help eobjc'
eswift -- For more information run 'help eswift'
fa11y -- For more information run 'help fa11y'
flicker -- For more information run 'help flicker'
fv -- For more information run 'help fv'
fvc -- For more information run 'help fvc'
hide -- For more information run 'help hide'
mask -- For more information run 'help mask'
mwarning -- For more information run 'help mwarning'
pa11y -- For more information run 'help pa11y'
pactions -- For more information run 'help pactions'
paltrace -- For more information run 'help paltrace'
panim -- For more information run 'help panim'
pca -- For more information run 'help pca'
pcells -- For more information run 'help pcells'
pclass -- For more information run 'help pclass'
pcomponents -- For more information run 'help pcomponents'
pcurl -- For more information run 'help pcurl'
pdata -- For more information run 'help pdata'
pdocspath -- For more information run 'help pdocspath'
pinternals -- For more information run 'help pinternals'
pinvocation -- For more information run 'help pinvocation'
pivar -- For more information run 'help pivar'
pjson -- For more information run 'help pjson'
pkp -- For more information run 'help pkp'
pmethods -- For more information run 'help pmethods'
pobjc -- For more information run 'help pobjc'
poobjc -- For more information run 'help poobjc'
poswift -- For more information run 'help poswift'
presponder -- For more information run 'help presponder'
pswift -- For more information run 'help pswift'
ptv -- For more information run 'help ptv'
pvc -- For more information run 'help pvc'
pviews -- For more information run 'help pviews'
rcomponents -- For more information run 'help rcomponents'
show -- For more information run 'help show'
slowanim -- For more information run 'help slowanim'
taplog -- For more information run 'help taplog'
unborder -- For more information run 'help unborder'
unmask -- For more information run 'help unmask'
unslowanim -- For more information run 'help unslowanim'
visualize -- For more information run 'help visualize'
vs -- For more information run 'help vs'
wivar -- For more information run 'help wivar'
For more information on any command, type 'help <command-name>'.
常用命令介绍
alamborder&alamunborder
如果给一个view添加了约束,但是该约束不足以确定它的位置,使用alamborder命令可以给其添加边框,常使用autolayout的话,该命令会很实用。通过help alamborder
可以看到它的语法是Syntax: alamborder [--color=color] [--width=width]
颜色默认是红色,宽度2,我试了几次alamborder [--color=green][--width=2]
发现颜色和宽度都是默认的,也没研究出来是哪里出错了。
例子,我给一个button添加了约束
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.backgroundColor = [UIColor grayColor];
[btn setTitle:@"按钮" forState:UIControlStateNormal];
[btn addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
[btn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.offset(10);
make.height.equalTo(@(50));
}];
可以看到约束不能确定button的x点和宽度,使用alamborder命令,即可看到button被添加了红色的边框,同时UIWindow的也被加了边框,好像是只要存在子view约束不完整,UIWindow也会被加上边框。
效果如下图:
Simulator Screen Shot 2016年5月30日 上午11.12.51.png
alamunborder和alamborder相反,该命令用于把alamborder设置的边框去掉
bmessage
给某个方法手动添加一个断点,你可能会说,加断点不用这么麻烦,我们平时加断点Xcode中左侧点击不就OK了吗,但是如果这个方法我们并没有实现呢,如下面这个例子,SecondVC
中的viewWillAppear:
病没有实现,现在输入bmessage [SecondVC viewWillAppear:]
命令添加断点,会给SecondVC父类的viewWillAppear:方法添加断点,并且子类是SecondVC的时候才生效。
(lldb) bmessage [SecondVC viewWillAppear:]
Setting a breakpoint at -[UIViewController viewWillAppear:] with condition (void*)object_getClass((id)$rdi) == 0x000000010835eb80
Breakpoint 2: where = UIKit`-[UIViewController viewWillAppear:], address = 0x000000010934f899
现在进入SecondVC,断点生效了
4F15E8E6-EED2-4AF4-88FF-800A50A90A49.pngborder&unborder
先通过help border
来看一下border的说明和语法,功能是可以给view设置边框颜色和宽度及其设置的层级深度,语法如下:
Syntax: border [--color=color] [--width=width] [--depth=depth] <viewOrLayer>
color:边框颜色(只能是black gray red green blue cyan yellow magenta orange purple brown这几种,否则会报错)
width:边框粗细
depth:层级深度(depth为0时,只设置view本身,其他值则设置view及更深层级的子view)
如下例子,我们给self.view及其1、2层级下的子view设置红色边框
(lldb) border -c red -w 2 -d 2 self.view
效果是这样的
Simulator Screen Shot 2016年5月30日 下午2.55.08.png
self.view的边框是我们设置的红色,但是层级下的边框颜色都是随机的,应该是为了防止view较多且有重合的时候无法分辨区域吧。另外我们也可以通过暂停程序,输入pview命令拿到view的地址,直接操作view的地址。
相反的,unborder就是取消设置边框,命令后只需要加view和层级深度这两个参数即可,如:(lldb) unborder self.view -d 2
参数的顺序可以不分先后。
fv&fvc
fv
和fvc
这两个命令是用来通过类名搜索当前内存中所存在的view和VC实例的,支持正则搜索,如果正则表达式语法掌握很好的话,会很方便。
(lldb) fv button
0x7f8d61515900 UIButton
0x7f8d6175b820 UIButtonLabel
(lldb) fvc second
0x7f8d617699e0 SecondVC
hide&show
hide和show命令用于隐藏和显示一个view,应用场景还是很常见的,想隐藏一个view看一下效果,使用hide命令,然后可以再使用show命令显示
(lldb) hide 0x7f8d6151bfc0
(lldb) show 0x7f8d6151bfc0
mask&unmask
mask命令是为一个view添加一个覆盖层(经试验,覆盖层的颜色是随机的),目的也是为了看到某个view的布局;unmask功能相反
下面的命令就是给正方形的view和导航栏添加一个覆盖层
(lldb) mask 0x7f8d6151bfc0
(lldb) mask 0x7f8d61430340
效果图:
390247E5-2350-4988-ADC1-314F428ADDB6.pngpcells
pcells命令可以打印层级最高的tableview当前可见的所有cell,比如我在金融首页打印,结果如下:
(lldb) pcells
<__NSArrayI 0x7fc682dc4740>(
<GMCJRMYBInfCell: 0x7fc683047a00; baseClass = UITableViewCell; frame = (0 263.094; 375 155); autoresize = W; layer = <CALayer: 0x7fc6856a67c0>>,
<GMCJXVipInfCell: 0x7fc683872a00; baseClass = UITableViewCell; frame = (0 478.094; 375 69); autoresize = W; layer = <CALayer: 0x7fc6857aaa10>>,
<GMCJXVipInfCell: 0x7fc68497aa00; baseClass = UITableViewCell; frame = (0 547.094; 375 69); autoresize = W; layer = <CALayer: 0x7fc685866680>>
)
pclass
pclass可以打印出一个对象的继承关系,如下,打印出0x7f8d6142e0c0对象的继承类的关系。
(lldb) pclass 0x7f8d6142e0c0
ViewController
| UIViewController
| | UIResponder
| | | NSObject
pcurl
以cur命令的形式打印NSURLRequest对象,如下,初始化一个NSURLRequest对象,并用pcurl打印
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
request_ = [[NSURLRequest alloc] initWithURL:url];
(lldb) pcurl request_
curl -X GET --connect-timeout 60 "http://www.baidu.com"
从结果中我们可以看出该请求的请求方式是GET
,超时时间是60s
,url
是http://www.baidu.com
pdata
解码打印一个NSData对象,相当于调用[NSString initWithData:encoding:]
,语法Syntax: pdata [--encoding=encoding] <data>
,命令后跟的是编码方式,默认是utf8,实例如下:
_strDemo = @"今天是个好天气";
dataDemo_ = [_strDemo dataUsingEncoding:NSUTF8StringEncoding];
(lldb) pdata dataDemo_
今天是个好天气
pdocspath
打印应用程序的Documents目录路径,语法是Syntax: pdocspath [--open]
,如果加了—open(-o),相当于open in Finder
,会在文件目录中打开,这点还是比较实用的。
(lldb) pdocspath -o
/Users/zhangbeibei/Library/Developer/CoreSimulator/Devices/70D5098B-52A0-441C-997E-DFB49567A80A/data/Containers/Data/Application/759F42BD-F267-4B9C-8816-3D9397EAB31C/Documents
D0882BA1-B02E-429C-B7D7-D70421E87743.png
pinternals
pinternals用来打印对象的成员变量,可以看到自定义的成员变量被打印出来了,但是系统自带的属性如view等并未打印
(lldb) pinternals self
(ViewController) $14 = {
UIViewController = {
UIResponder = {
NSObject = {
isa = ViewController
}
}
}
dicDemo_ = 0x00007fd1c371dbd0 3 key/value pairs
}
pivar
打印对象的某个成员变量,语法是Syntax: pivar <object> <ivarName>
,object
是要打印的对象,ivarName
变量名称
如下,打印出当前VC的view属性
(lldb) pivar self _view
<UIView: 0x7fd1c3418890; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7fd1c3418a00>>
pjson
将一个字典或数组json化并打印出来,语法是Syntax: pjson [--plain] <object>
但是试验了多次都报错,不知道是不是有bug,后续再研究研究
visualize
这是个很有意思的功能,它可以让你使用Mac的预览功能打开一个 UIImage, CGImageRef, UIView, 或 CALayer。这个功能可以帮我们用来定位一个view的具体内容,或者用来截图。
我们使用该命令查看view上的按钮,如下:
(lldb) visualize 0x7fb23bf180c0
可以看到它打开了预览,并展示了按钮所生成的图片
6E19F442-8289-434E-B55F-825F2ACF8420.pngpobjc&&poobjc
pobjc
等同于lldb
自有的p
命令
poobjc
等同于lldb
自有的po
命令
presponder
打印一个继承于presponder的控件的响应链,非常详细,我打印0x7fe8d9c29200
的响应链,如下:
(lldb) presponder 0x7fe8d9c29200
<UIButton: 0x7fe8d9c29200; frame = (100 220; 100 40); opaque = NO; layer = <CALayer: 0x7fe8d9c0ff50>>
| <UIView: 0x7fe8d9f04da0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7fe8d9f06f70>>
| | <ViewController: 0x7fe8d9c2b1c0>
| | | <UIViewControllerWrapperView: 0x7fe8d9c29c90; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7fe8d9c19b40>>
| | | | <UINavigationTransitionView: 0x7fe8d9d0c2a0; frame = (0 0; 375 667); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x7fe8d9d11f50>>
| | | | | <UILayoutContainerView: 0x7fe8d9c2d570; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x7fe8d9d1f830>; layer = <CALayer: 0x7fe8d9c2d990>>
| | | | | | <UINavigationController: 0x7fe8da02fa00>
| | | | | | | <UIWindow: 0x7fe8d9c29f60; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x7fe8d9c2ad60>; layer = <UIWindowLayer: 0x7fe8d9c298c0>>
| | | | | | | | <UIApplication: 0x7fe8d9d00ab0>
| | | | | | | | | <AppDelegate: 0x7fe8d9d10aa0>
ptv&pvc
ptv打印层级中最上面的tableview,如果没有则打印找不到的提示语
(lldb) ptv
<GMBTableView: 0x7f90e309c800; baseClass = UITableView; frame = (0 64; 375 554); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x7f90e5070e00>; layer = <CALayer: 0x7f90e505eee0>; contentOffset: {0, 180.5}; contentSize: {375, 1563.2064835693309}>
(lldb) ptv
Sorry, chump. I couldn't find a table-view. :'(
pvc打印当前存在的VC的层级关系
(lldb) pvc
<UINavigationController 0x7f8d61841600>, state: appeared, view: <UILayoutContainerView 0x7f8d6142fcf0>
| <ViewController 0x7f8d6142e0c0>, state: disappeared, view: <UIView 0x7f8d61751dc0> not in the window
| <SecondVC 0x7f8d617699e0>, state: appeared, view: <UIView 0x7f8d61757340>
pviews
这个命令可以打印出当前的view层级关系或某个指定view上的层级,这个命令有助于帮助我们在调试时定位问题,如我们添加了一个view没有展示,可以通过这个层级关系及描述找到问题所在。命令后不指定view默认打印当前存在的所有view层级关系,如下:
(lldb) pviews
<UIWindow: 0x7f81725141f0; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x7f8172515550>; layer = <UIWindowLayer: 0x7f8172510cf0>>
| <UIView: 0x7f8172517620; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7f8172513830>>
| | <_UILayoutGuide: 0x7f81725189b0; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x7f81725024d0>>
| | <_UILayoutGuide: 0x7f81725195f0; frame = (0 667; 0 0); hidden = YES; layer = <CALayer: 0x7f817250bee0>>
| | <UIView: 0x7f817261a580; frame = (100 100; 100 100); layer = <CALayer: 0x7f8172605ff0>>
| | <UIButton: 0x7f817261abe0; frame = (100 230; 100 50); opaque = NO; layer = <CALayer: 0x7f817260fc90>>
| | | <UIButtonLabel: 0x7f81726233c0; frame = (32 14.5; 36 21.5); text = '按钮'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7f817260cca0>>
| | | | <_UILabelContentLayer: 0x7f817241c770> (layer)
指定view则打印该view所包含的view层级,如指定当前vc上的view:
(lldb) pviews self.view
<UIView: 0x7f8172517620; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7f8172513830>>
| <_UILayoutGuide: 0x7f81725189b0; frame = (0 0; 0 20); hidden = YES; layer = <CALayer: 0x7f81725024d0>>
| <_UILayoutGuide: 0x7f81725195f0; frame = (0 667; 0 0); hidden = YES; layer = <CALayer: 0x7f817250bee0>>
| <UIView: 0x7f817261a580; frame = (100 100; 100 100); layer = <CALayer: 0x7f8172605ff0>>
| <UIButton: 0x7f817261abe0; frame = (100 230; 100 50); opaque = NO; layer = <CALayer: 0x7f817260fc90>>
| | <UIButtonLabel: 0x7f81726233c0; frame = (32 14.5; 36 21.5); text = '按钮'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x7f817260cca0>>
| | | <_UILabelContentLayer: 0x7f817241c770> (layer)
taplog
打印所点击的控件的描述信息。先暂停程序,然后输入taplog
命令,点击要打印的控件,然后控制台会输出所点击控件的信息(前提是该控件的用户交互打开了且可以响应点击)。输入命令后,暂停的程序会继续运行,这是我点击一个button,输出信息如下:
(lldb) taplog
Process 8448 resuming
<UIButton: 0x7f95d2724520; frame = (100 220; 100 40); opaque = NO; layer = <CALayer: 0x7f95d2713c40>>
注意:每输入一次命令,只能打印一次点击的信息
自定义命令
�我们也可以定义一些命令来满足自己的需求,前提是要懂python,会的童鞋感兴趣可以自己研究一下。
Chisel中的命令实现文件在/usr/local/Cellar/chisel/1.4.0/libexec/commands
路径下,虽然不懂语法,看看大致的实现思路还是受益匪浅的。