概述
LLDB是LLVM下的调试器。Xcode4.0开始,编译器开始使用LLVM,相应的调试器也从gdb改为LLDB。Xcode5.0之后所有工程均自动设置为使用LLDB
常用命令
help
help
列出所有命令help
<commond>列出某个命令更多细节,例如help print
-
print
打印需要查看的变量,例如print number
,简写为p
-
po(print object)
可以打印对象的description方法的结果 -
打印不同格式可以用
p/x number
打印16进制,p/t number
打印2进制,p/c char
打印字符
-
(lldb) e i = 10 (lldb) p i (Int) $R1 = 10 (lldb) p/x i (Int) $R2 = 0x000000000000000a (lldb) p/t i (Int) $R3 = 0b0000000000000000000000000000000000000000000000000000000000001010 (lldb) p/c "eeee" (String) $R4 = "eeee" (lldb)
expression
-
expression
可以改变一个值,简写e
(lldb) expression i (Int) $R7 = 1 (lldb) expression i = 5 (lldb) p i (Int) $R9 = 5 (lldb)
-
e -o -- object
可以打印一个对象,别名是po
(lldb) e -o -- view ▿ Optional<UIView> (lldb) po view ▿ Optional<UIView>
thread
thread backtrace
:作用是将线程的堆栈打印出来,别名bt
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = Fatal error: Index out of range
frame #0: 0x0000000106a39900 libswiftCore.dylib`_swift_runtime_on_report
...
frame #7: 0x0000000107202d79 libswiftSwiftOnoneSupport.dylib`generic specialization <preserving fragile attribute, Swift.Int> of Swift.Array.subscript.getter : (Swift.Int) -> A + 89
* frame #8: 0x00000001033a2659 LLDBDebug`ViewController.viewDidLoad(self=0x00007f9c9ff19ba0) at ViewController.swift:18
LLDB用*
标出了重要信息语句,我们只需要看前面带*
的语句就可以知道crash的原因是下标越界和发生的地方是ViewController中的第18行,我们只需要查看这行代码就行了
thread return
:让代码停止执行某个方法或者直接返回一个想要的值
2 Thread
2.1 堆栈打印 thread backtrace
如果嫌堆栈打印太长,可以加一个值限制,如bt 10,只打印
(lldb) bt 10
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x00000001005e4906 DiDi`-[FW_HomeCell_HotBill setDataSource:](self=0x00007fd3938a7800, _cmd="setDataSource:", dataSource=0x00006080001c8bb0) at FW_HomeCell.m:357
frame #1: 0x00000001009a9fd7 DiDi`-[FW_MyHomeTableView tableView:cellForRowAtIndexPath:](self=0x00007fd3921fec00, _cmd="tableView:cellForRowAtIndexPath:", tableView=0x00007fd3921fec00, indexPath=0xc000000000000316) at FW_MyHomeTableView.m:247
frame #2: 0x00000001055a2ab2 UIKit`-[UITableView _createPreparedCellForGlobalRow:withIndexPath:willDisplay:] + 750
frame #3: 0x00000001055a2cf8 UIKit`-[UITableView _createPreparedCellForGlobalRow:willDisplay:] + 74
frame #4: 0x0000000105577639 UIKit`-[UITableView _updateVisibleCellsNow:isRecursive:] + 2845
frame #5: 0x00000001055abccc UIKit`-[UITableView _performWithCachedTraitCollection:] + 111
frame #6: 0x0000000105592e7a UIKit`-[UITableView layoutSubviews] + 233
frame #7: 0x00000001054f955b UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1268
frame #8: 0x0000000105114904 QuartzCore`-[CALayer layoutSublayers] + 146
frame #9: 0x0000000105108526 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 370
流程控制
当我们在调试程序的时候,我们经常用下面这4个按钮:
我们可以通过LLDB命令来完成上面的操作
c/continue/thread continue
: 这三个命令效果都等同于上图中第一个按钮的。表示程序继续运行n/next/thread step-over
: 这三个命令效果等同于上图第二个按钮。表示单步运行s/step/thread step-in
: 这三个命令效果等同于上图第三个按钮。表示进入某个方法finish/step-out
: 这两个命令效果等同于第四个按钮。表示直接走完当前方法,返回到上层frame
断点管理
breakpoint list
可以看到所有断点,简写br li
breakpoint set
可以创建断点,简写br
在调试器中直接更新UI
call view.backgroundColor = UIColor.blue
继续运行之后就可以看到界面的变化
打印UI所有层级属性
po let s = UIApplication.shared.keyWindow?.perform("recursiveDescription"); print(s)
先编辑断点,在触发短点的