国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

Chisel-LLDB命令插件,讓調(diào)試更Easy

2019-11-07 23:59:57
字體:
供稿:網(wǎng)友

chisel是facebook開源的LLDB插件,方便開發(fā)者在開發(fā)過程中提升開發(fā)效率,或是方便從新接手的一個舊項目中快速熟悉起來。

以下內(nèi)容多來自博客:https://blog.cnbluebox.com/ 因為有些東西都是一樣的,就直接拷過來了,有部分是我后來補充的。

LLDB 是一個有著 REPL 的特性和 C++ ,Python 插件的開源調(diào)試器。LLDB 綁定在 Xcode 內(nèi)部,存在于主窗口底部的控制臺中。調(diào)試器允許你在程序運行的特定時暫停它,你可以查看變量的值,執(zhí)行自定的指令,并且按照你所認為合適的步驟來操作程序的進展。(這里有一個關(guān)于調(diào)試器如何工作的總體的解釋。)

相信每個人或多或少都在用LLDB來調(diào)試,比如po一個對象。LLDB的是非常強大的,且有內(nèi)建的,完整的 Python 支持。今天我們主要介紹一個 facebook 開源的 lldb 插件 Chisel。可以讓你的調(diào)試更Easy.

1.安裝Chisel

源碼地址: Chisel

Chisel 使用 homebrew 來安裝,如果你沒有安裝homebrew, 參考 homebrew。

12
brew updatebrew install chisel

安裝完成按照安裝日志上的提示,在~/.lldbinit文件中添加一行,沒有則新建。 提示類似如下:

123
==> CaveatsAdd the following line to ~/.lldbinit to load chisel when Xcode launches: command script import /usr/local/opt/chisel/libexec/fblldb.py

做好上面的步驟,然后重啟Xcode就可以嘗試下了。

注:使用命令行“ls -a”查看是否有“.lldbinit”的文件,如果沒有該文件,我們可以利用“touch ~/.lldbinit”創(chuàng)建該文件。然后將如下圖中的地址復(fù)制到文件中,保存退出。重啟Xcode,暫停后在控制臺輸入“help”,如果出現(xiàn)如圖二的顯示則表示安裝成功。(“brew uninstall”可以卸載已安裝的chisel)

圖一

圖二

2.內(nèi)置命令

Chisel 為lldb提供了新增的便捷命令,是非常實用的命令

2.1 pviews

這個命令可以遞歸打印所有的view,并能標示層級,相當于 UIView 的私有輔助方法 [view recursiveDescription] 。 善用使用這個功能會讓你在調(diào)試定位問題時省去很多麻煩。

使用示例:

123456789
(lldb) pviews view<TestView: 0x18df8070; baseClass = UIControl; frame = (144 9; 126 167); layer = <CALayer: 0x18df8150>> | <UIView: 0x18df81d0; frame = (0 0; 126 126); userInteractionEnabled = NO; layer = <CALayer: 0x18df8240>> | <UIImageView: 0x18df8330; frame = (0 0; 126 126); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x18df83b0>> | <UILabel: 0x18df8460; frame = (0 135; 126 14); text = 'haha'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x18df7fb0>> | | <_UILabelContentLayer: 0x131a3d50> (layer) | <UILabel: 0x18df8670; frame = (0 155; 126 12); text = 'hahaha'; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x18df8730>> | | <_UILabelContentLayer: 0x131bea10> (layer) | <UIImageView: 0x18df88d0; frame = (0 9; 28 27); hidden = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x18df8ba0>>

2.2 pvc

這個命令也是遞歸打印層級,但是不是view,而是viewController。利用它我們可以對viewController的結(jié)構(gòu)一目了然。 其實蘋果在IOS8也默默的添加了 UIViewController 的一個私有輔助方法[UIViewController _PRintHierarchy] 同樣的效果。(注:配合符號斷點,也可以定位ViewController。在符號斷點中輸入“viewDidLoad”,便會在所有初始化ViewController時都會斷一下。cmd+shift+o是快速定位)

預(yù)覽效果:

1234567891011121314
(lldb) pvc<TabBarController: 0x13772fd0; view = <UILayoutContainerView; 0x151b3a30>; frame = (0, 0; 414, 736)> | <UINavigationController: 0x1602b800; view = <UILayoutContainerView; 0x1b00aca0>; frame = (0, 0; 414, 736)> | | <FirstViewController: 0x16029c00; view = <UIView; 0x1b01e1c0>; frame = (0, 0; 414, 736)> | <UINavigationController: 0x138c5200; view = <UILayoutContainerView; 0x1316a080>; frame = (0, 0; 414, 736)> | | <SecondViewController: 0x16030400; view = <UIView; 0x2094b370>; frame = (0, 0; 414, 736)> | | | <SecondChildViewController: 0x15af6000; view = <UIView; 0x18d4e650>; frame = (0, 64; 414, 628)> | <UINavigationController: 0x1383ca00; view = <UILayoutContainerView; 0x13180070>; frame = (0, 0; 414, 736)> | | <ThirdViewController: 0x138ddc00; view = <UIView; 0x18df6650>; frame = (0, 0; 414, 736)> | | | <ThirdChild1ViewController: 0x1393fe00; view = <UIView; 0x131ec000>; frame = (0, 0; 414, 672)> | | | <ThirdChild2ViewController: 0x138dce00; view = <UIView; 0x204075a0>; frame = (414, 0; 414, 672)> | | | <ThirdChild3ViewController: 0x138a8e00; view = <UIView; 0x20426250>; frame = (828, 0; 414, 672)> | <UINavigationController: 0x160eca00; view = <UILayoutContainerView; 0x152f7d90>; frame = (0, 0; 414, 736)> | | <FourViewController: 0x13157cc0; view not loaded>

是不是方便很多呢,而且還可以看到 viewController 是否已經(jīng) viewDidLoad .

2.3 visualize

這是個很有意思的功能,它可以讓你使用Mac的預(yù)覽打開一個 UIImage, CGImageRef, UIView, 或 CALayer。 這個功能或許可以幫我們用來截圖、用來定位一個view的具體內(nèi)容。 但是在我試用了一下,發(fā)現(xiàn)暫時還是只能在模擬器時使用,真機還不行。(注:visualize可以用在已打印出的對象的地址(地址也可以通過viewdebuger獲取)預(yù)覽該對象,例如“visualize0x7f82617107f0”)

使用簡單:

1
(lldb) visualize imageView

2.4 fv & fvc

fvfvc 這兩個命令是用來通過類名搜索當前內(nèi)存中存在的view和viewController實例的命令,支持正則搜索。

如:

123456789
(lldb) fv scrollView0x18d3b8c0 UIScrollView0x137d0c50 UIScrollView0x131b1580 UIScrollView0x131b2070 UIScrollView(lldb) fvc Home0x1393fe00 HomeFeedsViewController0x138a8e00 HomeFeedsViewController(lldb)

2.5 show & hide

這兩個命令用來顯示和隱藏一個指定的 UIView . 你甚至不需要Continue Progress. 就可以看到效果。

2.6 mask/umask border/unborder

這兩組命令用來標識一個view或layer的位置時用, mask用來在view上覆蓋一個半透明的矩形, border可以給view添加邊框。但是在我實際使用的過程中mask總是會報錯,估計是有bug, 那么mask/unmask 一般不要用好了,用border命令是一樣的效果,反正二者的用途都是找到一個對應(yīng)的view.

2.7 caflush

這個命令會重新渲染,即可以重新繪制界面, 相當于執(zhí)行了 [CATransaction flush] 方法,要注意如果在動畫過程中執(zhí)行這個命令,就直接渲染出動畫結(jié)束的效果。

當你想在調(diào)試界面顏色、坐標之類的時候,可以直接在控制臺修改屬性,然后caflush就可以看到效果啦,是不是要比改代碼,然后重新build省事多了呢。

例, 其中 $122 即是目標UIView:

1234
(lldb) p view(long) $122 = 140718754142192(lldb) e (void)[$122 setBackgroundColor:[UIColor greenColor]](lldb) caflush

2.8 bmessage

這個命令就是用來打斷點用的了,雖然大家斷點可能都喜歡在圖形界面里面打,但是考慮一種情況:我們想在 [MyViewController viewWillAppear:] 里面打斷點,但是 MyViewController并沒有實現(xiàn)viewWillAppear: 方法, 以往的作法可能就是在子類中實現(xiàn)下viewWillAppear:,然后打斷點,然后rebuild。

那么幸好有了 bmessage命令。我們可以不用這樣就可以打這個效果的斷點: (lldb) bmessage -[MyViewController viewWillAppear:] 上面命令會在其父類的viewWillAppear: 方法中打斷點,并添加上了條件:[self isKindOfClass:[MyViewController class]]

2.9 border

這個命令是用來給某個對象加邊框,方便與其他的視圖對象有所區(qū)別。

border -c red -w 2 0x7f82617107f0(對象地址),此時模擬器會自動刷新界面并對該對象加上邊框?qū)挾葹?的紅色邊框。

unborder 0x7f82617107f0,這條命令是去掉剛才加的邊框?qū)傩?/code>。

2.10 caflush補充

這個命令是在你做了修改view的外觀之后,可以讓屏幕立刻刷新成你修改的外觀樣式。因為在一些chisel命令中是默認刷新的,但是有些命令是需要我們自己去手動刷新的。

在控制臺輸入“po [0x7f82617107f0 setBackgroundColor:[UIColor redColor]]”后,需要在輸入“caflush”模擬器的界面才會有變化。但是不建議我們?nèi)ナ謩痈淖儗ο蟮谋尘吧驗槲覀儽仨毴ジ倪^來或者重新啟動工程才能還原。通常建議是加邊框來區(qū)別。

2.11 presponder

這個命令是輸出對象的響應(yīng)者鏈。

presponder 0x7f82617107f0,在控制器中從APPDelegate到當前對象的響應(yīng)者鏈,不會顯示同級的對象,方便我們梳理一些層級關(guān)系和響應(yīng)事件的執(zhí)行。

2.12 taplog

這個命令是在你程序中斷時,你敲擊模擬器屏幕的任何地方,控制器會打印到你觸摸的view。方便我們快速查找獲取觸摸的view地址,以便利用其它的命令來做其它的操作。注意:我們需要先輸入“taplog”,再去點擊屏幕。

2.13 pcalss

這個命令可以打印當前對象的類的繼承關(guān)系。

pclass 0x7f82617107f0結(jié)果:

UITableViewLabel   | UILabel   |    | UIView   |    |    | UIResponder   |    |    |    | NSObject

2.14 pinternals

這個命令是打印對象的繼承關(guān)系、對象屬性、實例方法等詳細信息,其中包括我們自定義的屬性和方法。

輸入: pinternals 0x7fde6681dc00結(jié)果:(UITableViewCell) $5 = {  UIView = {    UIResponder = {      NSObject = {        isa = UITableViewCell      }      _hasOverrideClient = false      _hasOverrideHost = false      _hasInputAssistantItem = false    }    _constraintsExceptingSubviewAutoresizingConstraints = nil    _cachedTraitCollection = 0x00006000000dc9a0    _layer = 0x0000608000029be0    _layerRetained = nil    _gestureInfo = nil    _gestureRecognizers = nil    _window = 0x00007fde66006a90    _subviewCache = 0x000060000005c920 @"2 elements"    _templateLayoutView = nil    _charge = 0    _tag = 0    _viewDelegate = nil    _backgroundColorSystemColorName = 0x000060800005c110 @"tableCellPlainBackgroundColor"    _countOfMotionEffectsInSubtree = 0    _countOfTraitChangeRespondersInDirectSubtree = 3    _cachedScreenScale = 3    _layoutSubviewsCount = 0    _retainCount = 4    _tintAdjustmentDimmingCount = 0    _shouldArchiveUIAppearanceTags = false    _wantsDeepColorDrawing = true    _interactionTintColor = nil    _layoutMarginsGuide = nil    _minXVariable = nil    _minYVariable = nil    _boundsWidthVariable = nil    _boundsHeightVariable = nil    _layoutEngine = nil    _layoutDebuggingIdentifier = nil    _stashedLayoutVariableObservations = nil    _internalConstraints = nil    _continuousCornerRadius = 0    _countOfFocusedAncestorTrackingViewsInSubtree = 0    _semanticContentAttribute = 0    _contentSizeNotificationToken = 0x000060800005c2f0    _readableContentGuide = nil    __preferedContentsFormat = 0    _previewingSegueTemplateStorage = nil    __presentationControllerToNotifyOnLayoutSubviews = nil  }  _tableView = nil  _layoutManager = 0x0000608000002520  _target = nil  _editAction = <no value available>  _accessoryAction = <no value available>  _oldEditingData = nil  _editingData = nil  _rightMargin = 0  _indentationLevel = 0  _indentationWidth = 10  _reuseIdentifier = 0x0000000107074b10 @"Cell"  _floatingContentView = nil  _lineBreakModeBeforeFocus = 0  _contentView = 0x00007fde66002050  _imageView = nil  _textLabel = 0x00007fde6600e3e0  _detailTextLabel = nil  _backgroundView = nil  _selectedBackgroundView = nil  _multipleSelectionBackgroundView = nil  _selectedOverlayView = nil  _selectionFadeDuration = 0.5  _backgroundColor = 0x000060800007d5c0  _separatorColor = 0x0000600000077640  _separatorEffect = nil  _topShadowColor = 0x000060800005c170  _bottomShadowColor = 0x000060800005c1a0  _sectionBorderColor = 0x0000600000077640  _floatingSeparatorView = nil  _topShadowAnimationView = nil  _bottomShadowAnimationView = nil  _badge = nil  _unhighlightedStates = 0x0000000000000000  _highlightingSupport = nil  _selectionSegueTemplate = nil  _accessoryActionSegueTemplate = nil  _accessoryActionPreviewingSegueTemplateStorage = nil  _accessoryView = nil  _editingAccessoryView = nil  _customAccessoryView = nil  _customEditingAccessoryView = nil  _separatorView = 0x00007fde63f089a0  _topSeparatorView = nil  _topShadowView = nil  _editableTextField = nil  _lastSelectionTime = 0  _deselectTimer = nil  _textFieldOffset = 114  _indexBarWidth = 0  _returnAction = <no value available>  _selectionTintColor = 0x0000608000055cf0  _accessoryTintColor = nil  _reorderControlImage = nil  _menuGesture = 0x00007fde6600e070  _representedIndexPath = nil  _focusable = false  _swipeToDeleteConfirmationView = nil  _swipeToDeleteCancelationGesture = nil  _clearBlendingView = nil  _swipeToDeleteDistancePulled = 0  _sectionCornerRadius = 0  _sectionBorderWidth = 0  _defaultMarginWidth = 20  _editControlFocusGuide = nil  _reorderControlFocusGuide = nil  _constants = 0x0000600000002410  _isLayoutEngineSuspended = false}

3. 自定義命令

我們也可以自定義插件,不過前提是要懂一些 python。 比如設(shè)計一個打印keyWindow的windowLevel的命令:

創(chuàng)建python腳本文件 /magical/commands/example.py :

1234567891011121314151617181920
#!/usr/bin/python# Example file with custom commands, located at /magical/commands/example.pyimport lldbimport fblldbbase as fbdef lldbcommands():  return [ PrintKeyWindowLevel() ]class PrintKeyWindowLevel(fb.FBCommand):  def name(self):    return 'pkeywinlevel'  def description(self):    return 'An incredibly contrived command that prints the window level of the key window.'  def run(self, arguments, options):    # It's a good habit to explicitly cast the type of all return    # values and arguments. LLDB can't always find them on its own.    lldb.debugger.HandleCommand('p (CGFloat)[(id)[(id)[UIapplication sharedApplication] keyWindow] windowLevel]')

其中定義了PrintKeyWindowLevel的類,需要實現(xiàn) name descriptionrun 方法來分別告訴名稱、描述、和執(zhí)行實體。

創(chuàng)建好腳本后,然后在前面安裝時創(chuàng)建的 ~/.lldbinit文件中添加一行:

1
script fblldb.loadCommandsInDirectory('/magical/commands/')

然后重啟Xcode之后就可以使用自定義的命令啦。

參考文獻:

Chisel官方說明

與調(diào)試器共舞 – LLDB 的華爾茲


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 红桥区| 炎陵县| 习水县| 运城市| 靖安县| 宁国市| 武冈市| 岫岩| 英山县| 乃东县| 阿巴嘎旗| 桃园县| 门源| 中方县| 读书| 涞水县| 虹口区| 临沭县| 岚皋县| 阿尔山市| 三明市| 三亚市| 高淳县| 荆门市| 濉溪县| 曲阜市| 通许县| 山东| 梁河县| 沙河市| 师宗县| 阆中市| 塔河县| 兰考县| 南岸区| 灵川县| 上饶县| 肃宁县| 聊城市| 安新县| 安龙县|