用Homebrew安装chisel
搞定Homebrew之后,你就可以用他来安装chisel了
1
2
|
brew
update
brew
install
chisel
|
官网的命令里有一个brew update
,是用来更新Homebrew版本的,如果你是新安装的Homebrew,可以省略掉这条命令
在~/.lldbinit
中添加命令
安装好之后,terminal中会出现这个东西
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
|
意思是需要把这个命令command script import /usr/local/opt/chisel/libexec/fblldb.py
加到~/.lldbinit
文件中
我们将命令其添加进去即可。如果你已经添加过一次了,不需要再次添加
1
2
|
touch
~
/
.
lldbinit
echo
"command script import /usr/local/opt/chisel/libexec/fblldb.py"
>>
~
/
.
lldbinit
|
重启一下Xcode,安装完成
更新
如果你想更新chisel,只需要输入更新的命令即可
1
|
brew
upgrade
chisel
|
命令
Autolayout
autolayout中有一种bug叫Ambiguous Layouts,意思是你设置的约束不足以确定view的位置或大小。比如你只设置了X轴的位置,没有设置Y轴的位置
autolayout提供了专门判断和查找这类问题的方法:
1
2
|
hasAmbiguousLayout
.
Available
for
both
iOS
and
OS
X
.
Call
this
method
on
a
misplaced
view
.
It
returns
YES
if
the
view’
s
frame
is
ambiguous
.
Otherwise
,
it
returns
NO
.
_autolayoutTrace
.
Available
as
a
private
method
in
iOS
.
Call
this
method
on
a
view
.
It
returns
a
string
with
diagnostic
information
about
the
entire
view
hierarchy
containing
that
view
.
Ambiguous
views
are
labeled
,
and
so
are
views
that
have
translatesAutoresizingMaskIntoConstraints
set
to
YES
.
|
hasAmbiguousLayout
用于判断是否存在Ambiguous Layouts
_autolayoutTrace
用于查找存在的Ambiguous Layouts
但是即使有查找的方法,真正去做这个事儿也比较费时费力的,这时候chisel给我们提供了更为方便的命令
alamborder
给存在Ambiguous Layouts
的view加上border,方便查找哪些View存在问题
语法:
1
|
Syntax
: alamborder
[
--
color
=
color
]
[
--
width
=
width
]
|
--color
/-c
: border的颜色,参数为string类型,比如’red’, ‘green’, ‘magenta’等,不设置默认为红色。--width
/-w
: border的宽度,参数为CGFloat类型,不设置默认宽度为2。
e.g: 假设我们写了这么一段代码,可以明显看出,我们没有设置X轴的位置。
1
2
3
4
5
6
|
UIView
*subview
=
[
UIView
new
]
;
[
self
.
view
addSubview
:subview
]
;
[
subview
mas_makeConstraints
:
^
(
MASConstraintMaker
*make
)
{
make
.
top
.
offset
(
100
)
;
make
.
size
.
equalTo
(
@
100
)
;
}
]
;
|
运行代码之后,在LLDB控制台输入alamborder
1
|
(
lldb
)
alamborder
|
所有带有Ambiguous Layouts
的view立即会被渲染上红色border
可以看到,subview的边框已经变为红色,另外只要有一个View存在Ambiguous Layouts
,UIWindow的边框也会变为红色,这就有效的避免了宽度或者高度为0的Ambiguous Layouts
不宜察觉的缺陷。
alamunborder
将alamborder
设置的border去掉.
语法:
1
|
Syntax
: alamunborder
|
e.g: 刚刚设置的border,在lldb控制台输入alamunborder
即可去掉边框
1
|
(
lldb
)
alamborder
|
paltrace
打印某个View的autolayout详细信息,相当于调用_autolayoutTrace
语法:
1
|
Syntax
: paltrace
<view>
|
<view>
: 需要打印详细信息的view,不传参数默认为keyWindow
e.g: 查看一下keyWindow上有哪个view存在Ambiguous Layouts
1
2
3
4
5
6
7
8
9
10
11
|
(
lldb
)
paltrace
•
UIWindow
:
0x7ff450d2fb50
-
AMBIGUOUS
LAYOUT
|
•
UIView
:
0x7ff450e14430
|
|
*
_UILayoutGuide
:
0x7ff450d30e90
|
|
*
_UILayoutGuide
:
0x7ff450d31230
|
|
*UIView
:
0x7ff450d32870
-
AMBIGUOUS
LAYOUT
for
UIView
:
0x7ff450d32870.minX
{
id
:
46
}
Legend
:
*
-
is
laid
out
with
auto
layout
+
-
is
laid
out
manually
,
but
is
represented
in
the
layout
engine
because
translatesAutoresizingMaskIntoConstraints
=
YES
•
-
layout
engine
host
|
我们可以看到,UIView:0x7ff450d32870
存在Ambiguous Layouts
,原因是缺少minX
。也就是没有设置X轴的位置
在LLDB中,我们执行的最多的可能就是打印操作了,chisel专门为这类操作封装了一些打印命令
pviews
循环打印view层级,正常情况下等效于调用recursiveDescription
命令
1
2
3
|
// 下面2条命令等效
(
lldb
)
po
[
self
.
view
recursiveDescription
]
(
lldb
)
pviews
self
.
view
|
语法:
1
|
pviews
[
--
up
]
[
--
depth
=
depth
]
<aView>
|
--up
/-u
: 以view为起始位置,向上打印,直到打印到window层--depth
/-d
: 传入int类型,表示打印的层数,0表示没有限制
e.g: 打印一下self.view层级
1
2
3
4
5
6
7
|
(
lldb
)
pviews
self
.
view
<
UIView
:
0x7fee7ae1fa60
;
frame
=
(
0
0
;
375
667
)
;
autoresize
=
W
+
H
;
layer
=
<
CALayer
:
0x7fee7ae1d3c0
>>
|
<
UIButton
:
0x7fee7ae1dd90
;
frame
=
(
54
244
;
46
30
)
;
opaque
=
NO
;
autoresize
=
RM
+
BM
;
layer
=
<
CALayer
:
0x7fee7ae1e300
>>
|
<
UIView
:
0x7fee7ae1f2e0
;
frame
=
(
35
312
;
240
128
)
;
autoresize
=
RM
+
BM
;
layer
=
<
CALayer
:
0x7fee7ae1f660
>>
|
<
_UILayoutGuide
:
0x7fee7ae1fc20
;
frame
=
(
0
0
;
0
0
)
;
hidden
=
YES
;
layer
=
<
CALayer
:
0x7fee7ae20030
>>
|
<
_UILayoutGuide
:
0x7fee7ae20b30
;
frame
=
(
0
0
;
0
0
)
;
hidden
=
YES
;
layer
=
<
CALayer
:
0x7fee7ae1d100
>>
|
<
UILabel
:
0x7fee7ae1d3f0
;
frame
=
(
0.4
150
;
58.25
20.5
)
;
text
=
'aaa'
;
userInteractionEnabled
=
NO
;
layer
=
<
_UILabelLayer
:
0x7fee7ae1bb30
>>
|
pvc
循环打印viewController的层级
语法:
1
|
Syntax
: pvc
<aViewController>
|
<aViewController>
: 表示要打印的viewController,不传参数默认viewController为当前的VC
e.g: 打印一下当前VC
1
2
3
4
|
(
lldb
)
pvc
<
UINavigationController
0x7fce1a03d800
>
,
state
: appeared
,
view
:
<
UILayoutContainerView
0x7fce19500c00
>
|
<
ViewController
0x7fce1c03a1d0
>
,
state
: disappeared
,
view
:
<
UIView
0x7fce19517b40
>
not
in
the
window
|
<
TableViewController
0x7fce1951f7b0
>
,
state
: appeared
,
view
:
<
UIView
0x7fce1c053e60
>
|
pclass
循环打印class的继承关系
语法:
1
|
Syntax
: pclass
<object>
|
<object>
: 要打印继承关系的对象
e.g: 打印一个View对象的继承关系
1
2
3
4
|
(
lldb
)
pclass
[
UIView
new
]
UIView
|
UIResponder
|
|
NSObject
|
presponder
打印响应链
语法:
1
|
Syntax
: presponder
<startResponder>
|
<startResponder>
: UIResponder对象,响应链开始位置
e.g: 打印一个tableView的响应链
1
2
3
4
|
(
lldb
)
presponder
tableView
<
UITableView
:
0x7fde54810e00
;
frame
=
(
0
0
;
0
0
)
;
clipsToBounds
=
YES
;
gestureRecognizers
=
<
NSArray
:
0x7fde52519ac0
>
;
layer
=
<
CALayer
:
0x7fde5253b4c0
>
;
contentOffset
:
{
0
,
0
}
;
contentSize
:
{
0
,
220
}
>
|
<
UIView
:
0x7fde5255c710
;
frame
=
(
0
0
;
600
600
)
;
autoresize
=
W
+
H
;
layer
=
<
CALayer
:
0x7fde5253b300
>>
|
|
<
TableViewController
:
0x7fde52491310
>
|
ptv
打印屏幕中显示的tableView,主要是与pcells
联合使用。如果有多个tableView,打印View层级中最上面的一个
语法:
1
|
Syntax
: ptv
|
e.g: 看看当前最上面是哪个tableView
1
2
|
(
lldb
)
ptv
<
UITableView
:
0x7fde52811800
;
frame
=
(
0
0
;
414
736
)
;
clipsToBounds
=
YES
;
autoresize
=
RM
+
BM
;
gestureRecognizers
=
<
NSArray
:
0x7fde526418d0
>
;
layer
=
<
CALayer
:
0x7fde5260adc0
>
;
contentOffset
:
{
0
,
-
64
}
;
contentSize
:
{
414
,
176
}
>
|
pcells
打印tableView中当前可见的cell,如果有多个tableView,打印View层级中最上面的tableView的可见cell
语法:
1
|
Syntax
: pcells
|
e.g: 看看当前可见的cell有哪些
1
2
3
4
5
6
7
|
(
lldb
)
pcells
<
_
_
NSArrayI
0x7fde52565a00
>
(
<
UITableViewCell
:
0x7fde52551180
;
frame
=
(
0
0
;
414
44
)
;
text
=
'BasicViewController'
;
autoresize
=
W
;
layer
=
<
CALayer
:
0x7fde52537140
>>
,
<
UITableViewCell
:
0x7fde5255bea0
;
frame
=
(
0
44
;
414
44
)
;
text
=
'DateViewController'
;
autoresize
=
W
;
layer
=
<
CALayer
:
0x7fde5255b1a0
>>
,
<
UITableViewCell
:
0x7fde5255e2d0
;
frame
=
(
0
88
;
414
44
)
;
text
=
'PPTViewController'
;
autoresize
=
W
;
layer
=
<
CALayer
:
0x7fde5255e270
>>
,
<
UITableViewCell
:
0x7fde5255fce0
;
frame
=
(
0
132
;
414
44
)
;
text
=
'TableViewController'
;
autoresize
=
W
;
layer
=
<
CALayer
:
0x7fde5255fa90
>>
)
|
pinternals
打印一个对象内部的成员变量,这个方法我一般用来看model属性
语法:
1
|
Syntax
: pinternals
<object>
|
<object>
: 需要打印内部成员变量的对象
e.g: 我们来看看一个model
内部属性的值
1
2
3
4
5
6
7
8
9
|
(
lldb
)
pinternals
model
(
Model
)
$
5
=
{
_name
=
0x000000010dd1c0a0
@"老鼠爱大米"
_URL
=
nil
_array
=
nil
_dictionary
=
nil
_string
=
nil
_model
=
nil
}
|
pdata
对编码过的NSData进行解码打印,等效于调用-[NSString initWithData:encoding:]
语法:
1
|
Syntax
: pdata
[
--
encoding
=
encoding
]
<data>
|
<data>
: 需要打印的data,NSData类型--encoding
/-e
: 编码类型,如果缺省默认为utf8,主要支持的类型有:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
-
ascii
,
-
utf8
,
-
utf16
,
unicode
,
-
utf16l
(
Little
endian
)
,
-
utf16b
(
Big
endian
)
,
-
utf32
,
-
utf32l
(
Little
endian
)
,
-
utf32b
(
Big
endian
)
,
-
latin1
,
iso88591
(
88591
)
,
-
latin2
,
iso88592
(
88592
)
,
-
cp1251
(
1251
)
,
-
cp1252
(
1252
)
,
-
cp1253
(
1253
)
,
-
cp1254
(
1254
)
,
-
cp1250
(
1250
)
,
|
e.g: 将一个utf8的NSData打印
1
2
|
(
lldb
)
pdata
-
e
=
utf8
data
老鼠爱大米
|
pkp
通过-valueForKeyPath:
打印key path
对应的值。
语法:
1
|
Syntax
: pkp
<keypath>
|
<keypath>
: 需要打印的路径,如self.view
说明:以前打印属性一般都用po obj.xxx
,现在我想用pkp obj.xxx
是一个更好的选择了,因为po obj.xxx
是调用getter方法,如果没有getter方法就无法打印了。pkp obj.xxx
不仅会调用getter方法,没有getter方法还会去查找成员变量
e.g: 打印一下self.view
1
2
|
(
lldb
)
pkp
self
.
view
<
UIView
:
0x7fd1da52d5d0
;
frame
=
(
0
0
;
375
667
)
;
autoresize
=
W
+
H
;
layer
=
<
CALayer
:
0x7fd1da52d740
>>
|
pivar
打印对象成员变量
语法:
1
|
Syntax
: pivar
<object>
<ivarName>
|
<object>
: id类型,要打印成员变量的对象<ivarName>
: 成员变量的名称,注意:如果是属性,对应成员变量的名字默认有_
前缀.
说明:个人觉得这个方法有点鸡肋,pinternals
一下子可以打印出所有的成员变量,用起来更方便,如果你只想打印某一个成员变量,用pkp
应该更爽
e.g: 继续打印self.view
1
2
|
(
lldb
)
pivar
self
_view
<
UIView
:
0x7fd1da52d5d0
;
frame
=
(
0
0
;
375
667
)
;
autoresize
=
W
+
H
;
layer
=
<
CALayer
:
0x7fd1da52d740
>>
|
pca
从渲染服务器的角度来打印layer tree
,命令的完整名字是PrintCoreAnimationTree
,相当于调用po [NSString stringWithCString:(char *)CARenderServerGetInfo(0, 2, 0)]
语法:
1
|
Syntax
: pca
|
说明:这个命令我也没用过,可能在某些情况下会有用处
e.g: 试一下pca
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
(
lldb
)
pca
==
context
956ecbbf
;
level
0
;
pid
28092
[
/
Applications
/
Xcode
.
app
/
Contents
/
Developer
/
Platforms
/
iPhoneSimulator
.
platform
/
Developer
/
SDKs
/
iPhoneSimulator
.
sdk
/
System
/
Library
/
CoreServices
/
SpringBoard
.
app
/
SpringBoard
]
(
secure
)
at
time
34552.989286
==
(
layer
[
375
667
0
]
[
0
0
375
667
]
[
0.5
0.5
0
]
(
transform
[
2
-
0
0
0
;
0
2
0
0
;
0
0
1
0
;
0
0
0
1
]
)
(
rasterizationScale
2
)
(
sublayers
(
array
(
layer
[
187.5
333.5
0
]
[
0
0
375
667
]
[
0.5
0.5
0
]
(
masksToBounds
true
)
(
sublayers
(
array
(
layer
[
187.5
333.5
0
]
[
0
0
375
667
]
[
0.5
0.5
0
]
(
backgroundColor
#000000ff)
(
sublayers
(
array
(
layer
[
187.5
333.5
0
]
[
0
0
375
667
]
[
0.5
0.5
0
]
(
sublayers
(
array
(
layer
[
187.5
333.5
0
]
[
0
0
375
667
]
[
0.5
0.5
0
]
(
sublayers
(
array
(
layer
[
187.5
333.5
0
]
[
0
0
375
667
]
[
0.5
0.5
0
]
(
sublayers
(
array
(
layer
[
187.5
333.5
0
]
[
0
0
375
667
]
[
0.5
0.5
0
]
(
masksToBounds
true
)
(
edgeAntialiasingMask
0
)
(
subclass
(
layer
-
host
adc504e5
.
.
.
.东西太多,省略部分内容
.
.
.
.
.
.
.
.
.
|
panim
显示是否正在执行动画,相当于调用p (BOOL)[UIView _isInAnimationBlock]
语法:
1
|
Syntax
: panim
|
说明:这个命令也并不常用
e.g: 在动画中,我们打印一下:
1
2
|
(
lldb
)
panim
(
BOOL
)
$
0
=
YES
|
Find
debug的时候,我们经常需要查找一些东西,比如View,viewController等。
fvc
根据viewController的Class名字查找VC
语法:
1
|
Syntax
: fvc
[
--
name
=
classNameRegex
]
[
--
view
=
view
]
|
--name
/-n
: string类型参数,根据viewController的Class名字查找viewController--view
/-v
: UIView类型参数,根据viewController拥有的view查找viewController
说明:上面2个option不能同时使用,只能使用某一个
e.g: 我们先根据名字查找一下VC
1
2
|
(
lldb
)
fvc
--
name
=
viewcontroller
0x7fd01a90f310
ViewController
|
e.g: 如果我们知道VC的view地址,也可以根据view来查找VC
1
2
3
|
(
lldb
)
fvc
--
view
=
0x7fd0194194d0
Found
the
owning
view
controller
.
<
ViewController
:
0x7fd01a90f310
>
|
fv
根据view的class名字查找view
语法:
1
|
Syntax
: fv
<classNameRegex>
|
<classNameRegex>
: view的class名称
e.g: 查找一下屏幕上的UILabel
1
2
|
(
lldb
)
fv
uilabel
0x7fd01a91dc10
UILabel
|
taplog
将点击的view打印出来,这个命令对于查找哪个view非常有帮助
语法:
1
|
Syntax
: taplog
|
说明:要查看的view必须能接收点击事件,也就是他的userInteractionEnabled
必须为YES才能被找到,UILabel和UIImageView默认userInteractionEnabled
为NO。
用法:我们需要先将程序暂停,输入taplog
,程序会自己运行,这时候点击你需要查看的view,控制台上就会显示出你刚刚点击的view相关信息
e.g: 我们先将程序暂停,输入taplog
1
2
|
(
lldb
)
taplog
Process
28421
resuming
|
程序会自己运行,我们再点击一个UIButton:
1
|
<
UIButton
:
0x7fe6785284e0
;
frame
=
(
54
244
;
46
30
)
;
opaque
=
NO
;
autoresize
=
RM
+
BM
;
layer
=
<
CALayer
:
0x7fe678528a50
>>
|
flicker
将view闪烁一下,以便于查找view的位置
语法:
1
|
Syntax
: flicker
<viewOrLayer>
|
<viewOrLayer>
需要闪烁的view或者layer
e.g: 我们来看看self.subView的位置
1
|
(
lldb
)
flicker
self
.
subView
|
vs
在view层级中搜索view,并显示出来
语法:
1
|
Syntax
: vs
<view>
|
<view>
:要查找的view
说明:相比fv
,vs
主要用于显示view在屏幕上的位置,2个命令可以配合使用
e.g: 假设我们要找屏幕上的一个view
首先用fv
查找UIView
类型的view
1
2
3
|
(
lldb
)
fv
uiview
0x7fbcf37228d0
UIView
0x7fbcf3725e90
UIView
|
然后看看这2个view到底哪个是我们想要找的view
1
2
3
4
5
6
7
8
9
10
|
(
lldb
)
vs
0x7fbcf3725e90
Use
the
following
and
(
q
)
to
quit
.
(
w
)
move
to
superview
(
s
)
move
to
first
subview
(
a
)
move
to
previous
sibling
(
d
)
move
to
next
sibling
(
p
)
print
the
hierarchy
<
UIView
:
0x7fbcf3725e90
;
frame
=
(
0
100
;
100
100
)
;
layer
=
<
CALayer
:
0x7fbcf3712a40
>>
|
输入命令后他会帮我们在屏幕上用粉红色标志出来vs
的view
控制台中vs
的view也有相应log。并且还提示有6种子命令:
w
: 移动到superviews
: 移动到第一个subviewa
: 移动到前面的同级viewd
: 移动到后面的同级viewp
: 打印出层级q
: 退出
如果这个不是我们要找的view,可以使用w
,s
,a
,d
,p
命令继续查找
Display
debug的时候,可能有一小半的工作是跟UI打交道,关于UI显示上的东西,也有几个命令
caflush
刷新UI界面。一般我们用LLDB命令改变UI,UI并不会立即更新,我们需要使用caflush
刷新界面
语法:
1
|
Syntax
: caflush
|
e.g: 我们用命令将label的背景色改为红色
1
2
3
4
|
(
lldb
)
fv
uilabel
0x7fb3919189d0
UILabel
(
lldb
)
e
[
(
(
UILabel
*
)
0x7fb3919189d0
)
setBackgroundColor
:
[
UIColor
redColor
]
]
(
lldb
)
caflush
|
border
给View或者layer加上border
语法:
1
|
Syntax
: border
[
--
color
=
color
]
[
--
width
=
width
]
<viewOrLayer>
|
--color
/-c
: 边框颜色,string类型,比如:’red’, ‘green’ ‘magenta’等,不设置默认为红色--width
/-w
: 边框宽度,不设置默认为2<viewOrLayer>
: 需要设置边框的view或者layer
e.g: 给刚刚的label加上边框
1
2
3
|
(
lldb
)
fv
uilabel
0x7fe713901f10
UILabel
(
lldb
)
border
0x7fe713901f10
|
unborder
去掉view或者layer的border
语法:
1
|
Syntax
: unborder
<viewOrLayer>
|
e.g: 将刚刚加上的border去掉
1
|
(
lldb
)
unborder
0x7fe713901f10
|
mask
给view添加一个半透明的矩形mask,用来查看view的位置
语法:
1
|
Syntax
: mask
[
--
color
=
color
]
[
--
alpha
=
alpha
]
<viewOrLayer>
|
--color
/-c
: mask的颜色,string类型,比如:’red’, ‘green’,’magenta’等,不设置默认为红色--alpha
/-a
: mask的透明度,不设置默认为0.5<viewOrLayer>
: 需要添加mask的view或者layer
e.g: 假如label是隐藏的,我们给他添加一个mask,看看他的位置在哪儿
1
2
3
|
(
lldb
)
fv
uilabel
0x7fe713901f10
UILabel
(
lldb
)
mask
0x7fe713901f10
|
unmask
将添加的mask去掉
语法:
1
|
Syntax
: unmask
<viewOrLayer>
|
<viewOrLayer>
: 需要去掉mask的view或者layer
e.g: 我们将刚刚添加的mask去掉
1
|
(
lldb
)
unmask
0x7fe713901f10
|
使用命令之后,我们可以看到什么都没有了,因为label是hidden的
show
显示一个view或者layer,相当于执行view.hidden = NO
语法:
1
|
Syntax
: show
<viewOrLayer>
|
<viewOrLayer>
: 需要显示的view或者layer
e.g: 将刚刚的label显示出来
1
|
(
lldb
)
show
0x7fe713901f10
|
hide
隐藏一个view或者layer,相当于执行view.hidden = YES
语法:
1
|
Syntax
: hide
<viewOrLayer>
|
<viewOrLayer>
: 需要隐藏的view或者layer
e.g: 又把label隐藏
1
|
(
lldb
)
hide
0x7fe713901f10
|
可以看到label位置什么都没有了
slowanim
减慢动画的速度
语法:
1
|
Syntax
: slowanim
<speed>
|
<speed>
: 动画的速度,速度越大,动画越快。1表示原始速度。不传参数默认为0.1
e.g: 原始动画我们设置为1s
1
2
3
|
[
UIView
animateWithDuration
:
1
animations
:
^
{
self
.
subView
.
frame
=
frame
;
}
]
;
|
暂停程序,将动画放慢5倍
1
|
(
lldb
)
slowanim
0.2
|
我们可以看到动画变慢了:
unslowanim
取消slowanim
效果,将动画速度变为正常
语法:
1
|
Syntax
: unslowanim
|
e.g: 我们将刚刚的slowanim
效果取消
1
|
(
lldb
)
unslowanim
|
Preview
预览功能,帮助我们用命令查看一个view或者图片的真正样子
visualize
用预览App打开UIImage, CGImageRef, UIView, CALayer等对象
语法:
1
|
Syntax
: visualize
<target>
|
<target>
: 需要预览的对象,id类型
e.g: 我们来看看某个image的样子
1
|
(
lldb
)
visualize
image
|
Debug
LLDB主要用于Debug,chisel怎么可能缺少debug相关命令呢?
wivar
为对象的成员变量设置watchpoint
,更多watchpoint
相关知识请阅读<小笨狼与LLDB的故事>
语法:
1
|
Syntax
: wivar
<object>
<ivarName>
|
<object>
: 需要为成员变量设置watchpoint
的对象。id类型<ivarName>
: 成员变量的名字,注意一般属性对应的成员变量带有_
前缀
e.g: 为self.subView设置watchpoint
1
2
|
(
lldb
)
wivar
self
_subView
Remember
to
delete
the
watchpoint
using
: watchpoint
delete
1
|
这时候,_subView值改变就会中断程序
bmessage
根据方法名设置断点
语法:
1
|
Syntax
: bmessage
<expression>
|
<expression>
: 设置断点的方法名,如:-[MyView setFrame:]
,+[MyView awesomeClassMethod]
,-[0xabcd1234 setFrame:]
等
说明:一般设置断点,如果这个方法本类没有实现,是父类实现的,断点是无效的。bmessage
有效避免了这种缺陷,即使本类没有实现,也能设置上断点
e.g: 给self中的btnAction:
方法设置一个断点
1
2
3
|
(
lldb
)
bmessage
-
[
self
btnAction
:
]
Setting
a
breakpoint
at
-
[
ViewController
btnAction
:
]
with
condition
(
void
*
)
(
id
)
$
rdi
==
0x00007ff2485311e0
Breakpoint
4
: where
=
TLLDB
`
-
[
ViewController
btnAction
:
]
at
ViewController
.
m
:
42
,
address
=
0x000000010c4bb620
|
binside
通过一个相对地址,给framework(library)设置断点
语法:
1
|
Syntax
: binside
<address>
|
<address>
: framework的相对地址
pinvocation
打印方法调用堆栈,仅支持x86
语法:
1
|
Syntax
: pinvocation
[
--
all
]
|
--all
/-a
: 表示打印所有堆栈,不设置默认只打印当前堆栈
说明:与bt
命令类似,不过信息比bt
打印得更详细,遗憾的是只能支持x86
e.g: 打印一下当前堆栈
1
2
3
4
|
(
lldb
)
pinvocation
frame
#0: 0x000962aa TMasonry`-[ViewController viewDidLoad](self=0x7bf2d9c0, _cmd="viewDidLoad") + 234 at ViewController.m:28
NSInvocation
:
0x7bf433e0
self
:
0x7bf2d9c0
|
打印所有堆栈:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
(
lldb
)
pinvocation
-
a
frame
#0: 0x000962aa TMasonry`-[ViewController viewDidLoad](self=0x7bf2d9c0, _cmd="viewDidLoad") + 234 at ViewController.m:28
NSInvocation
:
0x7d2bb050
self
:
0x7bf2d9c0
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#1: 0x008062ae UIKit`-[UIViewController _sendViewDidLoadWithAppearanceProxyObjectTaggingEnabled] + 44
NSInvocation
:
0x7be18a50
self
:
0x7bf2d9c0
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#2: 0x0080adce UIKit`-[UIViewController loadViewIfRequired] + 1384
NSInvocation
:
0x7bf0cc40
self
:
0x7bf2d9c0
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#3: 0x008569f9 UIKit`-[UINavigationController _layoutViewController:] + 52
NSInvocation
:
0x7d340c90
self
:
0x7c89ee00
Argument
:
0xbff69108
,
address
of
@
}
0x7bf2d9c0
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#4: 0x008572b1 UIKit`-[UINavigationController _updateScrollViewFromViewController:toViewController:] + 421
NSInvocation
:
0x7d340cc0
self
:
0x7c89ee00
2
Arguments
:
0xbff69158
,
address
of
@
}
0x0
0xbff6915c
,
address
of
@
}
0x7bf2d9c0
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#5: 0x00857458 UIKit`-[UINavigationController _startTransition:fromViewController:toViewController:] + 145
NSInvocation
:
0x7bf24870
self
:
0x7c89ee00
3
Arguments
:
0xbff69298
,
address
of
i
}
0
0xbff6929c
,
address
of
@
}
0x0
0xbff692a0
,
address
of
@
}
0x7bf2d9c0
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#6: 0x00858854 UIKit`-[UINavigationController _startDeferredTransitionIfNeeded:] + 1038
NSInvocation
:
0x7bf16b50
self
:
0x7c89ee00
Argument
:
0xbff692f8
,
address
of
@
}
0x0
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#7: 0x00859ada UIKit`-[UINavigationController __viewWillLayoutSubviews] + 68
NSInvocation
:
0x7be18930
self
:
0x7c89ee00
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#8: 0x00a35c4a UIKit`-[UILayoutContainerView layoutSubviews] + 252
NSInvocation
:
0x7bf26ab0
self
:
0x7bf40d40
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#9: 0x0070b008 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 810
NSInvocation
:
0x7bf25da0
self
:
0x7bf40d40
Argument
:
0xbff693b8
,
address
of
@
}
0x7bf40f80
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#10: 0x01b23059 libobjc.A.dylib`-[NSObject performSelector:withObject:] + 70
NSInvocation
:
0x7d2bb6c0
self
:
0x7bf40d40
2
Arguments
:
0xbff693d8
,
address
of
:
}
layoutSublayersOfLayer
:
0xbff693dc
,
address
of
@
}
0x7bf40f80
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#11: 0x0496b80a QuartzCore`-[CALayer layoutSublayers] + 144
NSInvocation
:
0x7bf134c0
self
:
0x7bf40f80
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#12: 0x0495f4ee QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 388
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#13: 0x0495f352 QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 26
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#14: 0x04951e8b QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 317
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#15: 0x04985e03 QuartzCore`CA::Transaction::commit() + 561
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#16: 0x049866c4 QuartzCore`CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 92
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#17: 0x01f66ffe CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#18: 0x01f66f5e CoreFoundation`__CFRunLoopDoObservers + 398
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#19: 0x01f5c108 CoreFoundation`CFRunLoopRunSpecific + 504
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#20: 0x01f5befb CoreFoundation`CFRunLoopRunInMode + 123
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#21: 0x00639206 UIKit`-[UIApplication _run] + 540
NSInvocation
:
0x7d21fc00
self
:
0x7d30bfe0
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#22: 0x0063ebfa UIKit`UIApplicationMain + 160
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#23: 0x00096a0a TMasonry`main(argc=1, argv=0xbff6a898) + 138 at main.m:14
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
frame
#24: 0x031caa21 libdyld.dylib`start + 1
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
--
-
|
Accessibility
这个模块的命令主要利用了UIAccessibility
相关特性,需要开启Accessibility功能才能使用,UIAccessibility
详细资料可以阅读UIAccessibility
fa11y
根据view的accessibilityLabel查找view
语法:
1
|
Syntax
: fa11y
<labelRegex>
|
<labelRegex>
: 需要匹配的text
说明:UILabel,UIButton的accessibilityLabel
等于title
e.g: 我们根据显示的文案,查找相应的控件
1
2
|
(
lldb
)
fa11y
妈妈
(
UILabel
0x176b5bd0
)
妈妈叫你回家吃饭了
|
pa11y
打印view层级中所有的accessibilityLabel
语法:
1
|
Syntax
: pa11y
<aView>
|
<aView>
: 需要打印层级的View,UIView类型
e.g: 我们打印一下self.view层级中所有的accessibilityLabel
1
2
3
4
|
(
lldb
)
pa11y
self
.
view
UIView
self
.
view
|
(
UIButton
0x176b4600
)
Button
|
(
UILabel
0x176b5bd0
)
妈妈叫你回家吃饭了
|
End
chisel的命令就介绍到这里,东西挺多的,没必要全部都记住,我把这个写出来就打算当做一个文档,以后记不起哪个命令就查一下自己的博客。
不过chisel确实是个好东西,工欲善其事,必先利其器。要想要方便的调bug,chisel绝对值得你拥有
原文链接: http://ios.jobbole.com/83589/
GitHub: https://github.com/gkassabli/chisel