说说XcodeLLDB调试的那些事儿

非 Y 不嫁゛ 提交于 2020-03-27 06:29:28

使用场景之一,接收他人的项目,快速理清其层次结构,可以打标识符断点,如下图

viewDidLoadBreak

每一个VC,都加了个在viewDidLoad方法处的断点,这样运行程序时,逐步断点,便可以理清层次,
但是,需要手动不断的继续,依旧不是很好
如果使用LLDB,就事半功倍~
先上效果图
LLDBDemo

LIDB简史

Xcode5之前的调试器使用的是GDB,如果你不幸使用,那感觉简直了~然后伴随着Xcode5的发布,LLDB调试器取而代之,成为Xcode工程中默认的调试器,它和LVVM编译器一起,带给开发者丰富的流程控制和数据检测的调试功能.LLDB为Xcode提供了底层调试环境,其中,包括内嵌在Xcode IDE中的调试区域的控制面板,在这里我们可以直接调用LLDB命令.

chisel facebook团队良心出品的LLDB扩展

chisel 安装(需已有Homebrew,其安装很易,如若困惑可私信,这里不展开说明)

 brew update
 brew install chisel 

安装结束后会打印出路径如 /usr/local/opt/chisel/libexec/fblldb.py
添加下述命令行到 ~/.lldbinit file

 vi ~/.lldbinit
...
command script import /path/to/fblldb.py 

_注意:_要将将上述/path/to/fblldb.py ,路径替换为安装成功后的打印出路径如:/usr/local/opt/chisel/libexec/fblldb.py

特别的如果不存在~/.lldbinit file.
可以使用touch ~/.lldbinit 来创建它.

然后,需要重启Xcode,方能使之生效.

LLDB常见命令

Command Description iOS OS X
pviews Print the recursive view description for the key window. Yes Yes
pvc Print the recursive view controller description for the key window. Yes No
visualize Open a UIImage, CGImageRef, UIView, CALayer, NSData (of an image), UIColor, CIColor, or CGColorRef in Preview.app on your Mac. Yes No
fv Find a view in the hierarchy whose class name matches the provided regex. Yes No
fvc Find a view controller in the hierarchy whose class name matches the provided regex. Yes No
show/hide Show or hide the given view or layer. You don't even have to continue the process to see the changes! Yes Yes
mask/unmask Overlay a view or layer with a transparent rectangle to visualize where it is. Yes No
border/unborder Add a border to a view or layer to visualize where it is. Yes Yes
caflush Flush the render server (equivalent to a "repaint" if no animations are in-flight). Yes Yes
bmessage Set a symbolic breakpoint on the method of a class or the method of an instance without worrying which class in the hierarchy actually implements the method. Yes Yes
wivar Set a watchpoint on an instance variable of an object. Yes Yes
presponder Print the responder chain starting from the given object. Yes Yes
... ... and many more!

pviews

该命令是最常用的命令,主要是用来查看布局中view的层级关系的。

pviews
图中command+R运行程序后,点击暂停按钮,就可进入lldb控制台,输入pivews命令查看当前布局中view的层级关系。

border/unborder

这两个命令分别是给要查看的view添加边框和移除边框,可以在lldb下输入help border查看具体的用法,如果我要给第二个view添加一个颜色为蓝色,宽度为2的边框,之后再用unborder命令移除,操作如下:
border/unborder
通过help border命令知道border的使用格式如下:

Options:
--color/-c <color>; Type: string; A color name such as 'red', 'green',
 'magenta', etc.
 --width/-w <width>; Type: CGFloat; Desired width of border.
Syntax: border [--color=color] [--width=width] <viewOrLayer>

其中viewOrLayer表示你要修改的view的地址,我们通过pviews命令知道,第二个view的地址是0x7feae2d605f0,所以我们输入

border -c blue -w 2 0x7feae2d605f0  //添加边框
unborder 0x7feae2d605f0   //移除边框

注意我在输入每个border/unborder命令时,右侧模拟器第二个view的变化。
view的层级关系。

pinternals

这个命令主要是打印view的内部详细信息,太具体了,有需要的可以好好研究研究:
pinternals

(lldb) pinternals 0x7fa59c2446f0
(WKCompositingView) $451 = {
  UIView = {
    UIResponder = {
      NSObject = {
        isa = WKCompositingView
      }
      _hasAlternateNextResponder = false
      _hasInputAssistantItem = false
    }
    _constraintsExceptingSubviewAutoresizingConstraints = 0x00007fa59c248910 @"0 elements"
    _cachedTraitCollection = nil
    _layer = 0x00007fa599d81ba0
    _layerRetained = nil
    _gestureInfo = nil
    _gestureRecognizers = nil
    _subviewCache = 0x00007fa599f027d0 @"0 elements"
    _templateLayoutView = nil
    _charge = 0
    _tag = 0
    _viewDelegate = nil
    _backgroundColorSystemColorName = nil
    _countOfMotionEffectsInSubtree = 0
    _countOfTraitChangeRespondersInDirectSubtree = 0
    _cachedScreenScale = 2
    _retainCount = 4
    _tintAdjustmentDimmingCount = 0
    _shouldArchiveUIAppearanceTags = false
    _interactionTintColor = nil
    _layoutMarginsGuide = nil
    _minXVariable = 0x00007fa59c223790
    _minYVariable = 0x00007fa59c2237b0
    _boundsWidthVariable = 0x00007fa59c223ae0
    _boundsHeightVariable = 0x00007fa59c223800
    _layoutEngine = 0x00007fa59c014820
    _layoutDebuggingIdentifier = nil
    _internalConstraints = nil
    _continuousCornerRadius = 0
    _countOfFocusedAncestorTrackingViewsInSubtree = 0
    _semanticContentAttribute = 0
    __presentationControllerToNotifyOnLayoutSubviews = nil
    _previewingSegueTemplateStorage = nil
    _contentSizeNotificationToken = nil
    _readableContentGuide = 0x00007fee7c508a00
  }
}

pclass

这个可以查看view的层级关系

pclass

图中先查看了UIView的层级关系,然后查看了一个第三方自定义的控件MMPlaceHolder的层级关系。

hide/show

这两个命令顾名思义,就是显示和隐藏某个指定的view,话不多说,上图(注意模拟器中第二个view的变化):
hide/show

taplog

这个命令在你点击屏幕后,lldb打印出你敲击屏幕时接收事件的view的信息。

taplog

注意,我是先输入的命令,然后点击了屏幕才打印出对应view的信息。

pvc

这个命令是打印当前的控制器层级,如下图,我定义了一个UINavigationController,ViewController作为它的根控制器。
pvc

bmessage

有这么中需求,在当前控制器没有实现某个方法(譬如:-viewWillAppear:)方法,但是我又想在该方法调用时触发中断,这个时候bmessage就派上用场了

bmessage

(lldb) eobjc id $controller=(id)0x7fe8ab72ab50 //设置controller变量指向当前ViewController
(lldb) bmessage [$controller viewDidAppear:] //给当前ViewController设置断点
Setting a breakpoint at -[UIViewController viewDidAppear:] with condition (void*)(id)$rdi == 0x00007fe8ab72ab50
Breakpoint 1: where = UIKit`-[UIViewController viewDidAppear:], address = 0x000000010e646d12

以上是Chisel最常用的一些命令.当然这个不是全部,算是抛砖引玉.欢迎一起交流.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!