iOS 调试篇

修复bug 占用我们日常开发的大部分时间,熟练的使用调试工具可以给我们节约大部分的时间。

LLDB 的常用命令

expression

expresion 是一个非常常用的命令,我们可以通过这个命令来执行一些表达式,这样我们就不需要重写运行工程了,例如:

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

我们也可以使用 expression 来输出我们关注的信息

(lldb) expression -O -- self.view //这时候 就会输出对象 UIView,注意 -O 代表输出的是一个对象 ,这里有另外一种简写方式 po.
<UIView: 0x7d2974a0; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7d294813>>

有时候我们自定义的类并没有重写description 方法,如果我们直接输出这个对象的话可能只会显示这个类名和地址,例如

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

这地址并不是我们想要的,我们想要的是这个对象内部信息,这里我推荐一个插件 chisel ,我们可以使用chisel 提供的命令来打印这个对象, 例如

(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
  }
}

这样我们就能看到这个对象的内部信息了。
chisel 还提供一些便捷的功能,比如打印 pviews 递归打印层级,不过我更喜欢使用 xcode 自带的debug view hierarchy,这样更加直观。

我们可以使用 pvc 递归输出试图控制器的层级关系,例如

(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 这样我们就可以在任何地方了解我们所有界面状态了。
在 xcode8 以后,我们也可以通过debug memory graph 来查看程序运行的内存状态。

thread

我们可以使用 thread backtrace 来输出线程的堆栈信息,例如

(lldb) thread backtrace  // 这个命令可以简写为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

监视某个变量的改变,有时候我们想知道一个对象在什么时候被修改了,我们可以使用 watchpoint set var,当var 改变的时候程序就就会停在改变的地方, 如果用 chisel
的话,我们可以使用 wivar 命令来监听值的变化,例如

(lldb) wivar self name
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,440评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,814评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,427评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,710评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,625评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,511评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,162评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,311评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,262评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,278评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,989评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,583评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,664评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,904评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,274评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,856评论 2 339

推荐阅读更多精彩内容