iOS调试技巧iOS 技术精选集

Xcode这些lldb、断点调试方法,你常用吗?

2018-02-05  本文已影响31人  wustzhy

<一>列举我常用的lldb调试

1.想要知道cell的indexPath吗?
通过断点处po cell得到cell的内存地址(或者通过debug view hierarchy),比如0x7fd66f913600,然后得到indexPath如下

po [(UITableView *)[0x7fd66f913600 superview] indexPathForCell:(UITableViewCell *)0x7fd66f913600]

当然,可以一步步获取:

1.通过po [0x7fd66f913600 superview]得到tableView地址 0x7fd66f918888
2.通过po [0x7fd66f918888 indexPathForCell: 0x7fd66f913600 ],有时很奇怪,需要加上类型强转,才能正确得到结果,所以保险可用 po [(UITableView *)0x7fd66f918888 indexPathForCell: (UITableViewCell *)0x7fd66f913600 ]

2.获取ViewController,根据当前view
通常通过debug view hierarchy 去看 viewController,挺耗时的,慢,所以有时会使用nextResponder

(lldb) po [(UIView *)0x7fd44c439bb0 nextResponder]
<ViewController: 0x7fd44c41b180>

3.获取对象的引用计数

po [0x7fd44c439bb0 valueForKey:@"retainCount"]

另外,通过上面方式,即可实测 重复addsubview 不会增加引用计数
[self.view addSubview:view1];
[self.view addSubview:view1];
[self.view addSubview:view1];
估计接口内部处理过了,所以- (BOOL)isDescendantOfView:(UIView *)view;方法不必用来判断一下,返回NO才执行addsubview,直接addsubview

4.精准定位到满足条件的某个cell
a> 最简单的,通过属性就可以解决的。比如,想在"北京"那个cell中断,即条件为cell.textLabel.text == @"北京",那么设置条件断点(双击”断点“)

image.png

b> 最复杂的,满足条件的cell太多,或条件会变(但我所跟定的cell不变),或没有可以直接获取的属性。我是这样处理的:通过debug view hierarchy,print Description of XX , 拿到所看到的那个cell的地址0x7fd8b360c290,然后 设置条件断点条件:[[NSString stringWithFormat:@"%lx",(long int)self] isEqualToString:@"7fd8b360c290"],图片略(同上)

5.监听变量 断点调试
watchpoint set命令用于添加一个watchpoint。只要这个地址中的内容变化了,程序就会中断。

(lldb) watchpoint set variable self->_type
Watchpoint created: Watchpoint 1: addr = 0x131512680 size = 8 state = enabled type = w
    watchpoint spec = 'self->_type'
    new value: CCMediaTypeVideo
image.png

删除watchpoint

(lldb) watchpoint delete 1

6. 执行表达式
expression命令的作用是执行一个表达式,并将表达式返回的结果输出

(lldb) e int32_t a = 1; OSAtomicIncrement32(&a);
error: 'OSAtomicIncrement32' has unknown return type; cast the call to its declared return type

根据报错原因 fix后

(lldb) e int32_t a = 5;printf("%d,%d",a,a++); (int32_t)OSAtomicIncrement32(&a);
(int32_t) $6 = 7
5,5(lldb) e int32_t a = 5;printf("%d,%d",a,++a); (int32_t)OSAtomicIncrement32(&a);
(int32_t) $7 = 7
5,6(lldb) 

......更多不一一列举咯

LLDB的命令其实还有很多,很多命令我也没玩过。就算玩过的命令,我们也非常容易忘记,下次可能就不记得是怎么用的了。还好LLDB给我们提供了2个查找命令的命令:help & apropos

(lldb) help watchpoint
The following subcommands are supported:
 
      command -- A set of commands for adding, removing and examining bits of
                 code to be executed when the watchpoint is hit (watchpoint
                 'commmands').
      delete  -- Delete the specified watchpoint(s).  If no watchpoints are
                 specified, delete them all.
      disable -- Disable the specified watchpoint(s) without removing it/them. 
                 If no watchpoints are specified, disable them all.
      enable  -- Enable the specified disabled watchpoint(s). If no watchpoints
                 are specified, enable all of them.
      ignore  -- Set ignore count on the specified watchpoint(s).  If no
                 watchpoints are specified, set them all.
      list    -- List all watchpoints at configurable levels of detail.
      modify  -- Modify the options on a watchpoint or set of watchpoints in
                 the executable.  If no watchpoint is specified, act on the
                 last created watchpoint.  Passing an empty argument clears the
                 modification.
      set     -- A set of commands for setting a watchpoint.
(lldb) apropos stop-hook
The following built-in commands may relate to 'stop-hook':
  _regexp-display          -- Add an expression evaluation stop-hook.
  _regexp-undisplay        -- Remove an expression evaluation stop-hook.
  target stop-hook         -- A set of commands for operating on debugger
                              target stop-hooks.
  target stop-hook add     -- Add a hook to be executed when the target stops.
  target stop-hook delete  -- Delete a stop-hook.
  target stop-hook disable -- Disable a stop-hook.
  target stop-hook enable  -- Enable a stop-hook.
  target stop-hook list    -- List all stop-hooks.

时间多的,可以去看👉熟练使用 LLDB,让你调试事半功倍


<二> get到的更厉害的lldb技能

----------------- 自定义lldb命令 by Facebook

(lldb) help
Debugger commands:
  apropos           -- List debugger commands related to a word or subject.
  breakpoint        -- Commands for operating on breakpoints (see 'help b' for
                       shorthand.)
  bugreport         -- Commands for creating domain-specific bug reports.
  command           -- Commands for managing custom LLDB commands.
···
··
·
Current user-defined commands:
  alamborder   -- Put a border around views with an ambiguous layout
  alamunborder -- Removes the border around views with an ambiguous layout
  binside      -- Set a breakpoint for a relative address within the
                  framework/library that's currently running. This does the
                  work of finding the offset for the framework/library and
                  sliding your address accordingly.
···
··
·
pclass       -- Print the inheritance starting from an instance of any class.
·
pvc          -- Print the recursion description of <aViewController>.
pviews       -- Print the recursion description of <aView>.
·
visualize    -- Open a UIImage, CGImageRef, UIView, or CALayer in Preview.app
                  on your Mac.
···
··
·

使用时常用的有: pvc,presponder,pclass,visualize

(1) pvc ,打印各层级控制器

(lldb) pvc
<BaseTabBarController 0x7f9456006800>, state: appeared, view: <UILayoutContainerView 0x7f9456e07ea0> not in the window
   | <BaseNavigationController 0x7f945481e000>, state: appeared, view: <UILayoutContainerView 0x7f94544f51c0> not in the window
   |    | <HPViewController 0x7f9455053c00>, state: appeared, view: <UIView 0x7f9456c36af0> not in the window
   | <BaseNavigationController 0x7f9454809a00>, state: disappeared, view: <UILayoutContainerView 0x7f9454409a10> not in the window
   |    | <LSTableViewController 0x7f94547eaff0>, state: disappeared, view: (view not loaded)
   | <BaseNavigationController 0x7f9456000000>, state: disappeared, view: <UILayoutContainerView 0x7f9456e00b60> not in the window
   |    | <MTeViewController 0x7f9456e00090>, state: disappeared, view: (view not loaded)
   + <BaseTabBarController 0x7f945581b200>, state: appeared, view: <UILayoutContainerView 0x7f94547f33d0>, presented with: <_UIFullscreenPresentationController 0x7f9456f1a1b0>
   |    | <BaseNavigationController 0x7f945485be00>, state: appeared, view: <UILayoutContainerView 0x7f9456d698d0>
   |    |    | <SHPViewController 0x7f945487f200>, state: appeared, view: <UIView 0x7f9456c6eb60>
   |    | <BaseNavigationController 0x7f94560afe00>, state: disappeared, view: <UILayoutContainerView 0x7f94546e1700> not in the window
   |    |    | <CTableViewController 0x7f9456d71090>, state: disappeared, view: (view not loaded)
   |    | <BaseNavigationController 0x7f9455028a00>, state: disappeared, view: <UILayoutContainerView 0x7f9456c1f3c0> not in the window
   |    |    | <LTableViewController 0x7f9456c1d800>, state: disappeared, view: (view not loaded)
   |    | <BaseNavigationController 0x7f94560a2a00>, state: disappeared, view: <UILayoutContainerView 0x7f9456e3e7f0> not in the window
   |    |    | <VTableViewController 0x7f94547f56c0>, state: disappeared, view: (view not loaded)
   |    | <BaseNavigationController 0x7f94548be800>, state: disappeared, view: <UILayoutContainerView 0x7f9456d75940> not in the window
   |    |    | <MTableViewController 0x7f9456d76170>, state: disappeared, view: (view not loaded)

这样,拿到一个新项目可以一键看清VC层级结构, 最后一个appeared状态的<SHPViewController 0x7f945487f200>, state: appeared 即是当前VC

(2) pclass,打印对象继承层级

(lldb) pclass 0x7f945487f200
SHPViewController
   | RTableViewController
   |    | BaseViewController
   |    |    | UIViewController
   |    |    |    | UIResponder
   |    |    |    |    | NSObject

(3) visualize,提供直观看图

(lldb) po [0x10ddaeaa0 image]
<UIImage: 0x1c42a3f60> size {12, 12} orientation 0 scale 2.000000
(lldb) visualize 0x1c42a3f60    //mac的preview会打开该图片

比 Xcode提供的Open With Preview好使,毕竟经常出现光标放在那里,却弹不出来这调试框

image.png

(4) presponder,看响应链

(lldb) presponder self
<ViewController: 0x7fd8b3404170>
   | <UIWindow: 0x7fd8b370c2c0; frame = (0 0; 375 667); autoresize = W+H; gestureRecognizers = <NSArray: 0x61000005bc30>; layer = <UIWindowLayer: 0x61000003d6e0>>
   |    | <UIApplication: 0x7fd8b3601280>
   |    |    | <AppDelegate: 0x61800003a940>
上一篇下一篇

猜你喜欢

热点阅读