美文网首页iOS 开发技巧大全
iOS开发之LLDB常用调试技巧

iOS开发之LLDB常用调试技巧

作者: ShawnDu | 来源:发表于2017-07-21 20:54 被阅读47次

原文地址
iOS开发之LLDB常用调试技巧
用好了LLDB,让调试变得轻松愉快,本文会写出并示例讲解一些常用的指令,以让你爱上它~~
Debug的技巧有NSLog, LLDB, 但是NSLog效率低下,尽量少用NSLog。LLDB中强大的功能,完全能取代NSLog。

调试技巧:NSLog

NSLog比printf的效率要低几十倍,因为NSLog会向ASL写log,同时向Terminal写log,而且同时会出现在Console.app中。NSLog尽量不要在release中打开,在Debug中可以写一个宏:

#ifdef DEBUG
#define NSLog(FORMAT, ...) do {fprintf(stderr,"%s:%d\t%s\n",[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);} while(0)
#else
#define NSSLog(...)
#endif

调试技巧:LLDB

设置断点

  • 在LLDB中设置断点,可以用breakpoint set命令(简写br set):
(lldb) br set -f WebpImageViewController.m -l 104
Breakpoint 10: where = DemoCollectOC`-[WebpImageViewController addTestButton] + 26 at WebpImageViewController.m:104, address = 0x000000010f8a859a
  • 用b也可以创建断点,不过格式不同:
(lldb) b WebpImageViewController.m:97
Breakpoint 12: where = DemoCollectOC`-[WebpImageViewController testDict] + 588 at WebpImageViewController.m:97, address = 0x000000010f8a84ac
  • b也可以在C语言函数上直接创建,断点停在函数的开始:
(lldb) b DecodeInto
Breakpoint 13: where = DemoCollectOC`DecodeInto + 30 at webp.c:453, address = 0x000000010f95977e
  • 也可以在自定义函数、OC函数上设置断点:
(lldb) br set -F "-[UIView setBackgroundColor:]"
Breakpoint 14: where = UIKit`-[UIView(Rendering) setBackgroundColor:], address = 0x0000000112acae65
  • Condition & Action断点

    在断点处右键编辑断点,Log Message可以在符合条件时断住并打印出自定义信息: Condition断点图Condition断点图 , 还有全局断点,符号断点。
  • 断点继续运行

thread return

打印当前线程堆栈:bt

打印所有线程中堆栈bt all

寻找栈地址对应代码位置: image

image lookup --address 0x000000000000

常用的po

po可以打印一个对象,p可以打印基本数据类型,po也可以打印出视图的层级关系:[self.view recursiveDescription],但打印不出frame,打印frame可以使用call来调用一句代码:call self.view.frame

LLDB更新UI

查看App整个层次:

(lldb) po [[[UIApplication sharedApplication] keyWindow] recursiveDescription]
<UIWindow: 0x7f96c7e0b080; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x608000244f80>; layer = <UIWindowLayer: 0x6080000288c0>>
   | <UILayoutContainerView: 0x7f96c7e07b90; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x608000247d40>; layer = <CALayer: 0x608000029840>>
   |    | <UINavigationTransitionView: 0x7f96c7d0a590; frame = (0 0; 375 667); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x600000025500>>
   |    |    | <UIViewControllerWrapperView: 0x7f96c7e0bc30; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x608000029b00>>
   |    |    |    | <UIView: 0x7f96c7f0e6d0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x608000025460>>
   |    |    |    |    | <_UILayoutGuide: 0x7f96c7f11040; frame = (0 0; 0 64); hidden = YES; layer = <CALayer: 0x6080000255c0>>
   |    |    |    |    | <_UILayoutGuide: 0x7f96c7c01550; frame = (0 667; 0 0); hidden = YES; layer = <CALayer: 0x600000024980>>
   |    |    |    |    | <UITableView: 0x7f96c801a000; frame = (0 0; 375 667);

在当前断点下,展示的为UITableView: 0x7f96c801a000,取到这个view:

(lldb) e id $myview = (id)0x7f96c801a000

改变颜色:

(lldb) e (void)[$myview setBackgroundColor:[UIColor redColor]]

我不想继续运行程序,还能看到颜色变化,也可以做到。渲染服务是一个另外的进程(backboardd),调试内容所在的进程被打断了,backdboardd也在运行着,可以用下面的命令也即时展示颜色改变:

(lldb) e (void)[CATransaction flush]

查找UIButton的target

如果你在LLDB中有一个button变量,可以新创建的,也可以是在UI中找到的,或者是断点处正在这个变量上,假设是断点在这个testButton变量上:

(lldb) po [testButton allTargets]
{(
    <WebpImageViewController: 0x7fb2b670e2f0>
)}
(lldb) po [testButton actionsForTarget:(id)0x7fb2b670e2f0 forControlEvent:0]
<__NSArrayM 0x60800005c3b0>(
testButtonPressed:
)

观察实例变量变化

后面跟变量地址

(lldb) watchpoint set e -- 0x0000600000228d40

非重写方法符号断点

在子类中没有实现viewDidAppear方法,而是在父类中实现的,用breakpoint设置不可以,需要用Chisel中bmessage命令:

(lldb) bmessage -[WebpImageViewController viewDidAppear:]
Setting a breakpoint at -[UIViewController viewDidAppear:] with condition (void*)object_getClass((id)$rdi) == 0x000000010888aeb0
Breakpoint 2: where = UIKit`-[UIViewController viewDidAppear:], address = 0x000000010babd132

参考文章

相关文章

网友评论

    本文标题:iOS开发之LLDB常用调试技巧

    本文链接:https://www.haomeiwen.com/subject/uwxykxtx.html