iOS 調(diào)試篇

修復(fù)bug 占用我們?nèi)粘i_發(fā)的大部分時(shí)間椅贱,熟練的使用調(diào)試工具可以給我們節(jié)約大部分的時(shí)間毅舆。

LLDB 的常用命令

expression

expresion 是一個(gè)非常常用的命令,我們可以通過這個(gè)命令來執(zhí)行一些表達(dá)式休讳,這樣我們就不需要重寫運(yùn)行工程了,例如:

  (lldb) expression -- self.view.backgroundColor = [UIColor greenColor]
  (lldb) expression -- (void)[CATransaction flush] // 用于刷新頁面,

我們也可以使用 expression 來輸出我們關(guān)注的信息

(lldb) expression -O -- self.view //這時(shí)候 就會(huì)輸出對(duì)象 UIView芹橡,注意 -O 代表輸出的是一個(gè)對(duì)象 ,這里有另外一種簡(jiǎn)寫方式 po.
<UIView: 0x7d2974a0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7d294813>>

有時(shí)候我們自定義的類并沒有重寫description 方法望伦,如果我們直接輸出這個(gè)對(duì)象的話可能只會(huì)顯示這個(gè)類名和地址,例如

(lldb) expression -O -- self
<JChatAboutMeViewController: 0x7d2974a0>

這地址并不是我們想要的林说,我們想要的是這個(gè)對(duì)象內(nèi)部信息煎殷,這里我推薦一個(gè)插件 chisel ,我們可以使用chisel 提供的命令來打印這個(gè)對(duì)象, 例如

(lldb) pinternals 0x7d2974a0
(JChatAboutMeViewController) $4 = {
  UIViewController = {
    UIResponder = {
      NSObject = {
        isa = JChatAboutMeViewController
      }
      _hasOverrideClient = '\0'
      _hasOverrideHost = '\0'
      _hasInputAssistantItem = '\0'
    }
    _overrideTransitioningDelegate = nil
    _view = nil
    _tabBarItem = nil
    _navigationItem = 0x7d4abf40
    _toolbarItems = nil
    _title = nil
    _nibName = nil
    _nibBundle = nil
    _parentViewController = 0x7cb84c00
    _childModalViewController = nil
    _parentModalViewController = nil
    _previousRootViewController = nil
    _modalTransitionView = nil
    _modalPreservedFirstResponder = nil
    _dimmingView = nil
    _dropShadowView = nil
    _currentAction = nil
    _storyboard = nil
    _externalObjectsTableForViewLoading = nil
    _topLevelObjectsToKeepAliveFromStoryboard = nil
    _savedHeaderSuperview = nil
    _savedFooterSuperview = nil
    _editButtonItem = nil
    _searchDisplayController = nil
    _strongSearchDisplayController = nil
    _modalTransitionStyle = 0
    _modalPresentationStyle = 0
    _lastKnownInterfaceOrientation = 0
    _popoverController = nil
    _containerViewInSheet = nil
    _recordedContentScrollView = nil
    _afterAppearance = nil
    _explicitAppearanceTransitionLevel = 0
    _interfaceBuilderKeyCommands = nil
    _addedKeyCommands = nil
    _overrideTraitCollections = nil
    _previewSourceViews = nil
    _retainCount = 0
    _ignoreAppSupportedOrientations = '\0'
    _viewHostsLayoutEngine = '\0'
    _storyboardIdentifier = nil
    _transitioningDelegate = nil
    _frozenTraitCollection = nil
    overrideUseCustomPresentation = '\0'
    _modalPresentationCapturesStatusBarAppearance = '\0'
    _disablesAutomaticKeyboardDismissal = '\0'
    _ignoresParentMargins = '\0'
    _childViewControllers = nil
    _customNavigationInteractiveTransitionDuration = 0
    _customNavigationInteractiveTransitionPercentComplete = 0
    _customTransitioningView = nil
    _lastNotifiedTraitCollection = nil
    _presentationController = nil
    _preferredFocusedItem = nil
    _navigationControllerContentOffsetAdjustment = 0
    _contentMargin = 16
    _topLayoutGuide = nil
    _bottomLayoutGuide = nil
    _topBarInsetGuideConstraint = nil
    _bottomBarInsetGuideConstraint = nil
    _storyboardSegueTemplates = nil
    _segueResponsibleForModalPresentation = nil
    _sourceViewControllerIfPresentedViaPopoverSegue = nil
    _modalSourceViewController = nil
    _presentedStatusBarViewController = nil
    _edgesForExtendedLayout = 15
    __childControllerToIgnoreWhileLookingForTransitionCoordinator = nil
    _presentingFocusedItem = nil
    _storyboardPreviewSegueTemplates = nil
    _storyboardCommitSegueTemplates = nil
    _storyboardPreviewingRegistrants = nil
    __embeddedView = 0xffffffff
    __embeddingView = 0x78b909c0
    __embeddedDelegate = 0x00007faa
    _originalPresentationController = 0x78af3630
    _temporaryPresentationController = 0x00007faa
  }
}

這樣我們就能看到這個(gè)對(duì)象的內(nèi)部信息了。
chisel 還提供一些便捷的功能腿箩,比如打印 pviews 遞歸打印層級(jí)豪直,不過我更喜歡使用 xcode 自帶的debug view hierarchy,這樣更加直觀珠移。

我們可以使用 pvc 遞歸輸出試圖控制器的層級(jí)關(guān)系弓乙,例如

(lldb) pvc
<JChatSwift.JChatMainTabViewController 0x7d49d560>, state: appeared, view: <UILayoutContainerView 0x7d479860>
   | <UINavigationController 0x7c3afc00>, state: appeared, view: <UILayoutContainerView 0x7be8e9a0>
   |    | <JChatConversationListViewController 0x7d49d2b0>, state: disappeared, view: <UIView 0x7d375320> not in the window
   |    | <JChatChattingViewController 0x7bfbdde0>, state: appeared, view: <UIView 0x7d373b30>
   | <UINavigationController 0x7eb7a000>, state: disappeared, view: <UILayoutContainerView 0x7d4a2c20> not in the window
   |    | <JChatContactsViewController 0x7bea3d70>, state: disappeared, view: <UILayoutContainerView 0x7d4a1d40> not in the window
   | <UINavigationController 0x7cb84c00>, state: disappeared, view: <UILayoutContainerView 0x7bf87590> not in the window
   |    | <JChatAboutMeViewController 0x7d2974a0>, state: disappeared, view:  (view not loaded)

通過 pvc 和 pinternals 這樣我們就可以在任何地方了解我們所有界面狀態(tài)了。
在 xcode8 以后钧惧,我們也可以通過debug memory graph 來查看程序運(yùn)行的內(nèi)存狀態(tài)暇韧。

thread

我們可以使用 thread backtrace 來輸出線程的堆棧信息,例如

(lldb) thread backtrace  // 這個(gè)命令可以簡(jiǎn)寫為bt
* thread #1: tid = 0x14169a, 0x001273e5 JChatSwift`JChatChattingViewController.viewDidLayoutSubviews(self=0x7b6bc560) -> () + 21 at JChatChattingViewController.swift:48, queue = 'com.apple.main-thread', stop reason = breakpoint 7.1
  * frame #0: 0x001273e5 JChatSwift`JChatChattingViewController.viewDidLayoutSubviews(self=0x7b6bc560) -> () + 21 at JChatChattingViewController.swift:48
    frame #1: 0x00127502 JChatSwift`@objc JChatChattingViewController.viewDidLayoutSubviews() -> () + 34 at JChatChattingViewController.swift:0
    frame #2: 0x039dc811 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1598
    frame #3: 0x0305c1b9 libobjc.A.dylib`-[NSObject performSelector:withObject:] + 59
    frame #4: 0x03791769 QuartzCore`-[CALayer layoutSublayers] + 141
    frame #5: 0x03784a47 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 401
    frame #6: 0x0378489d QuartzCore`CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 21
    frame #7: 0x0370e49f QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 339
    frame #8: 0x0373d290 QuartzCore`CA::Transaction::commit() + 498
    frame #9: 0x0373eda0 QuartzCore`CA::Transaction::flush_transaction() + 38
    frame #10: 0x0393685c UIKit`_afterCACommitHandler + 375
    frame #11: 0x022f676e CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
    frame #12: 0x022f66c7 CoreFoundation`__CFRunLoopDoObservers + 391
    frame #13: 0x022da3a6 CoreFoundation`__CFRunLoopRun + 1414
    frame #14: 0x022d9bab CoreFoundation`CFRunLoopRunSpecific + 395
    frame #15: 0x022d9a0b CoreFoundation`CFRunLoopRunInMode + 123
    frame #16: 0x06a1ab4c GraphicsServices`GSEventRunModal + 177
    frame #17: 0x06a1a9c7 GraphicsServices`GSEventRun + 80
    frame #18: 0x039077fb UIKit`UIApplicationMain + 148
    frame #19: 0x001a7ce1 JChatSwift`main + 145 at AppDelegate.swift:15
    frame #20: 0x06037799 libdyld.dylib`start + 1

我們可以看到程序停在JChatChattingViewController.swift:48 這一行

watchpoint

監(jiān)視某個(gè)變量的改變浓瞪,有時(shí)候我們想知道一個(gè)對(duì)象在什么時(shí)候被修改了懈玻,我們可以使用 watchpoint set var,當(dāng)var 改變的時(shí)候程序就就會(huì)停在改變的地方, 如果用 chisel
的話乾颁,我們可以使用 wivar 命令來監(jiān)聽值的變化,例如

(lldb) wivar self name
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末涂乌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子英岭,更是在濱河造成了極大的恐慌湾盒,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件诅妹,死亡現(xiàn)場(chǎng)離奇詭異罚勾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)吭狡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門荧库,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人赵刑,你說我怎么就攤上這事分衫。” “怎么了般此?”我有些...
    開封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵蚪战,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我铐懊,道長(zhǎng)邀桑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任科乎,我火速辦了婚禮壁畸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己捏萍,他們只是感情好太抓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著令杈,像睡著了一般走敌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上逗噩,一...
    開封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天掉丽,我揣著相機(jī)與錄音,去河邊找鬼异雁。 笑死捶障,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的纲刀。 我是一名探鬼主播残邀,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼柑蛇!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起驱闷,我...
    開封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤耻台,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后空另,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體盆耽,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年扼菠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了摄杂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡循榆,死狀恐怖析恢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情秧饮,我是刑警寧澤映挂,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站盗尸,受9級(jí)特大地震影響柑船,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜泼各,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一鞍时、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦逆巍、人聲如沸及塘。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽磷蛹。三九已至,卻和暖如春溪烤,著一層夾襖步出監(jiān)牢的瞬間味咳,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工檬嘀, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留槽驶,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓鸳兽,卻偏偏與公主長(zhǎng)得像掂铐,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子揍异,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容