expr指令
这个指令能够实时的执行代码中的代码逻辑,看下面:
可以直接修改变量的值,尤其是当需要根据状态做不同操作的时候,我们不需要注释代码,不需要改动代码,就能调试,万一改了之后,忘了改回来呢。
call
call是调用方法的意思,p/po也有此功能,call可以使用在没有返回值,不需要显示输出的情况下,比如设置view的颜色
(lldb) call [self.view setBackgroundColor:[UIColor redColor]]
这样就不用为了看改一下颜色的效果再进行build一次了,尤其是build一次还要经过漫长的等待
image
- image lookup --address寻址,定位异常代码位置
举例说明,下面这段代码,执行的时候必然会出现异常,因为越界了:
NSString *str = @"245656";
[str substringFromIndex:10];
崩溃信息如下:
2016-05-27 14:58:54.173 GomeEShop[61425:4544758] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSCFConstantString substringFromIndex:]: Index 10 out of bounds; string length 6'
*** First throw call stack:
(
0 CoreFoundation 0x000000010e99ad85 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000011360ddeb objc_exception_throw + 48
2 CoreFoundation 0x000000010e99acbd +[NSException raise:format:] + 205
3 Foundation 0x000000010f8698bd -[NSString substringFromIndex:] + 126
4 GomeEShop 0x00000001097c396f -[GMFPTGoodsDetailVC initNecessaryViews] + 3903
5 GomeEShop 0x00000001097c1c51 -[GMFPTGoodsDetailVC viewDidLoad] + 369
6 UIKit 0x00000001110ae984 -[UIViewController loadViewIfRequired] + 1198
7 UIKit 0x00000001110b493b -[UIViewController __viewWillAppear:] + 120
8 UIKit 0x00000001110e4750 -[UINavigationController _startCustomTransition:] + 1203
9 UIKit 0x00000001110f4b9b -[UINavigationController _startDeferredTransitionIfNeeded:] + 712
10 UIKit 0x00000001110f5d0b -[UINavigationController __viewWillLayoutSubviews] + 57
11 UIKit 0x00000001112a4503 -[UILayoutContainerView layoutSubviews] + 248
12 UIKit 0x0000000110fce980 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 703
13 QuartzCore 0x0000000110c85c00 -[CALayer layoutSublayers] + 146
14 QuartzCore 0x0000000110c7a08e _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 366
15 QuartzCore 0x0000000110c79f0c _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
16 QuartzCore 0x0000000110c6e3c9 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 277
17 QuartzCore 0x0000000110c9c086 _ZN2CA11Transaction6commitEv + 486
18 UIKit 0x0000000110f4019b _afterCACommitHandler + 174
19 CoreFoundation 0x000000010e8bfc37 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
20 CoreFoundation 0x000000010e8bfba7 __CFRunLoopDoObservers + 391
21 CoreFoundation 0x000000010e8b57fb __CFRunLoopRun + 1147
22 CoreFoundation 0x000000010e8b50f8 CFRunLoopRunSpecific + 488
23 GraphicsServices 0x000000011481bad2 GSEventRunModal + 161
24 UIKit 0x0000000110f13f09 UIApplicationMain + 171
25 GomeEShop 0x00000001091c0ebf main + 111
26 libdyld.dylib 0x0000000113ba992d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
通过异常信息,我们看到崩溃很可能发生在-[GMFPTGoodsDetailVCinitNecessaryViews]方法中,也就是地址0x00000001097c396f,我们输入以下命令来进行精确定位:
(lldb) image lookup --address 0x00000001097c396f
执行后输出以下信息
Address: GomeEShop[0x00000001006af96f] (GomeEShop.__TEXT.__text + 7000239)
Summary: GomeEShop`-[GMFPTGoodsDetailVC initNecessaryViews] + 3903 at GMFPTGoodsDetailVC.m:589
我们看到出错的位置在GMFPTGoodsDetailVC.m文件中的initNecessaryViews方法中,第589行
- image lookup --type查看类型
我们还可以使用image lookup命令来查看具体的类型,如下所示:
(lldb) image lookup --type UIImage
执行后输出了UIImage所包含的属性:
Best match found in /Users/zhangbeibei/Library/Developer/Xcode/DerivedData/GomeEShop-dhpyydtykrwzvpawiualtxfthsqy/Build/Products/Debug-iphonesimulator/GomeEShop.app/GomeEShop:
id = {0x00cabeb2}, name = "UIImage", byte-size = 8, decl = UIImage.h:53, compiler_type = "@interface UIImage : NSObject
@property ( readonly,getter = size,setter = <null selector>,nonatomic ) CGSize size;
@property ( readonly,getter = CGImage,setter = <null selector>,nonatomic ) CGImageRef CGImage;
@property ( readonly,getter = CIImage,setter = <null selector>,nonatomic ) CIImage * CIImage;
@property ( readonly,getter = imageOrientation,setter = <null selector>,nonatomic ) UIImageOrientation imageOrientation;
@property ( readonly,getter = scale,setter = <null selector>,nonatomic ) CGFloat scale;
@property ( readonly,getter = images,setter = <null selector>,nonatomic ) NSArray * images;
@property ( readonly,getter = duration,setter = <null selector>,nonatomic ) NSTimeInterval duration;
@property ( readonly,getter = capInsets,setter = <null selector>,nonatomic ) UIEdgeInsets capInsets;
@property ( readonly,getter = resizingMode,setter = <null selector>,nonatomic ) UIImageResizingMode resizingMode;
@property ( readonly,getter = alignmentRectInsets,setter = <null selector>,nonatomic ) UIEdgeInsets alignmentRectInsets;
@property ( readonly,getter = renderingMode,setter = <null selector>,nonatomic ) UIImageRenderingMode renderingMode;
@property ( readonly,getter = traitCollection,setter = <null selector>,copy,nonatomic ) UITraitCollection * traitCollection;
@property ( readonly,getter = imageAsset,setter = <null selector>,nonatomic ) UIImageAsset * imageAsset;
@property ( readonly,getter = flipsForRightToLeftLayoutDirection,setter = <null selector>,nonatomic ) BOOL flipsForRightToLeftLayoutDirection;
@end"
bt
我们可以用bt来打印调用堆栈,加all可打印所有thread的堆栈,如下图:
(lldb) bt
* thread #1: tid = 0x4558f6, 0x0000000113eedf06 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x0000000113eedf06 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x0000000113eb54ec libsystem_pthread.dylib`pthread_kill + 90
frame #2: 0x0000000113c4fcec libsystem_c.dylib`abort + 129
frame #3: 0x0000000113a4e051 libc++abi.dylib`abort_message + 257
frame #4: 0x0000000113a73ac9 libc++abi.dylib`default_terminate_handler() + 267
frame #5: 0x000000011360e046 libobjc.A.dylib`_objc_terminate() + 103
frame #6: 0x0000000113a7126e libc++abi.dylib`std::__terminate(void (*)()) + 8
frame #7: 0x0000000113a70ef9 libc++abi.dylib`__cxa_rethrow + 99
frame #8: 0x000000011360df5e libobjc.A.dylib`objc_exception_rethrow + 40
frame #9: 0x000000010e8b51b4 CoreFoundation`CFRunLoopRunSpecific + 676
frame #10: 0x000000011481bad2 GraphicsServices`GSEventRunModal + 161
frame #11: 0x0000000110f13f09 UIKit`UIApplicationMain + 171
* frame #12: 0x00000001091c0ebf GomeEShop`main(argc=1, argv=0x00007fff56aea5f8) + 111 at main.m:16
frame #13: 0x0000000113ba992d libdyld.dylib`start + 1
frame #14: 0x0000000113ba992d libdyld.dylib`start + 1
p 和 po
- p 通常用于打印基本数据类型的值。这个指令会默认生出一个临时变量,如$1
- po 打印变量的内容,如果是对象,其打印的内容由 -debugDescription 决定。
** Symbolic Breakpoint的使用**
CUICatalog:Invalid asset name supplied:
这个错误很常见,因为+[UIImage imageNamed:],name为nil,但是又不知道是哪个地方出错了,要用Method Sizeele吗?不用,此时可以用Symbolic Breakpoint来解决。
-
创建断点
Xcode左下角,添加断点“+”号,选择 Add Symbolic Breakpoint就可以了:
image.png -
编辑断点
创建好了会弹出断点编辑页面,也可以通过右击断点选择“Edit Breakpoint..”进入编辑页面
image.png
下面开始介绍一下这几个编辑项:
- Symbol
断点触发函数,有两种函数写法,一种是C函数样式,一种是OC方法样式。
C函数样式只需要写函数名,不用写后面的()和参数,例如NSLog
OC方法样式 [className methodName]([类名 方法名],不区分类方法和实例方法),如果写标记的这个类的方法被子类重写了则子类的方法也会触发断点。比如[UIViewController viewDidLoad] - Module
模块筛选,可以避免不同库中方法名或者函数名相同 - Condition
触发条件,如果不写的话,则每次调用这个方法都会进入断点。
以[UIImage imageNamed:]方法为例,参数不能为nil,则可以在Symbol中写入 [UIImage imageNamed:],Condition 填入 arg3开始为第一个参数),这样就能在运行中,如果遇到为nil的情况下就会触发断点。 - Ignore
触发开始次数。设置这个值可以忽略前面指定次数的触发。 - Action
触发活动,这里是当断点触发后要执行的动作,可以添加多条,执行的顺序是从上到下。一共有6种可执行类型。
5.1 Debugger Command
会在断点触发的时候执行LLDB命令。可以打印对象、修改对象值等功能。
5.2 Log Message
会在断点触发的时候打印日志。其中@exp@打印对象值,exp为对象名;%B表示断点名;%H表示当前断点触发的次数。
5.3 Sound
触发声音。感觉很炫酷,但没点用的功能。适合装逼。
-----下面三个还没试过-------
5.4 AppleScript
会在断点触发的时候执行Mac OS X内置的一种功能强大的脚本语言,具体写法可以自行百度AppleScript。
5.5 Capture GPU Frame
GPU帧捕获,具体作用还没研究出来。
5.6 Shell Command
会在断点触发的时候执行Shell命令。
网友评论