『導(dǎo)言』
iOS利用Xcode進(jìn)行Debug
調(diào)試的技巧很多,比如最常見的方式是打印Log,在一些工程中處處可見NSLog
。還有就是打斷點(diǎn)
的Debug
方式等。諸如此類,下面就自己在開發(fā)過程中常用的Xcode調(diào)試技巧簡單的做個(gè)總結(jié)。(斷點(diǎn)調(diào)試demo下載)
聲明: 此文僅為我個(gè)人理解,有不正確的地方請(qǐng)?zhí)岢鰧氋F的意見
和建議
!謝謝!
一、Xcode調(diào)試技巧之:NSLog
在OC語言中,打Log是采用NSLog方法。但是NSLog效率低下,可以打印出具體位置方法:(調(diào)試輸出Debug.h文檔下載)
#ifdef DEBUG
#define DLog(fmt, ...) NSLog((@"[文件名:%s]\n" "[函數(shù)名:%s]\n" "[行號(hào):%d] \n" fmt), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#define DeBugLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#define NSLog(...) NSLog(__VA_ARGS__);
#define MyNSLog(FORMAT, ...) fprintf(stderr,"[%s]:[line %d行] %s\n",[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, [[NSString stringWithFormat:FORMAT, ##__VA_ARGS__] UTF8String]);
#else
#define DLog(...)
#define DeBugLog(...)
#define NSLog(...)
#define MyNSLog(FORMAT, ...)
#endif
- 注意:
release
版本中應(yīng)該要去掉NSLog
。 - 例如:
- 代碼
NSArray *array = @[@"wo",@"shi",@"apple"];
DLog(@"打印數(shù)組%@",array);
- 打印結(jié)果(類名+方法+行號(hào)+打印內(nèi)容)
2017-03-31 17:08:23.730 控制臺(tái)調(diào)試[20594:350839] [文件名:/Users/zhaowenjuan/Desktop/êé??à??è∞?∞é???/êé??à??è∞?∞é???/ViewController.m]
[函數(shù)名:-[ViewController touchesBegan:withEvent:]]
[行號(hào):43]
打印數(shù)組(
wo,
shi,
apple
)
圖.DLog輸出邏輯分析
二、Xcode調(diào)試技巧之:LLDB
- 斷點(diǎn)調(diào)試執(zhí)行命令:
序號(hào) | 命令 | 說明 | 翻譯 | 范圍 |
---|---|---|---|---|
1 |
c /continue
|
goto next breakpoint; | 去執(zhí)行下一個(gè) 斷點(diǎn) |
斷點(diǎn)間
|
2 |
n /next
|
step over | 跳到某個(gè)斷點(diǎn)方法內(nèi)部
|
斷點(diǎn)內(nèi)
|
3 |
s /step
|
step into | 跳到某個(gè)斷點(diǎn)內(nèi)部的下一個(gè) 位置 |
斷點(diǎn)內(nèi)
|
4 | finish |
step out |
退出 某個(gè)斷點(diǎn)內(nèi)部的位置 |
斷點(diǎn)內(nèi)
|
-
斷點(diǎn)執(zhí)行命令示例圖:
斷點(diǎn)執(zhí)行圖標(biāo).gif
斷點(diǎn)執(zhí)行.gif - 斷點(diǎn)調(diào)試打印命令
序號(hào) | 命令 | 說明 | 舉例子 |
---|---|---|---|
1 | po |
print object 的縮寫,表示顯示對(duì)象的文本描述,如果對(duì)象不存在則打印nil
|
命令:po num </br>輸出 :8
|
2 | p | 打印基本數(shù)據(jù)類型
|
命令:p i </br>輸出:(int) $0 = 30
|
3 | call | 執(zhí)行一段代碼</br>一般只在不需要顯式輸出 ,或是無返回值 時(shí)使用call,用于動(dòng)態(tài) 調(diào)試插入調(diào)用代碼 |
命令:call NSLog(@"%@", @"zwj")
|
4 | expr | 動(dòng)態(tài)執(zhí)行指定表達(dá)式
|
命令:expr i = 101 </br>輸出:(int)$0 = 101
|
5 | bt | 打印當(dāng)前線程堆棧信息;<br /><br />如果要打印所有 線程堆棧信息,使用:bt all 即可。 |
\ |
6 | image | 常用來尋找棧地址對(duì)應(yīng)代碼位置:行號(hào)
|
例如:<br />NSArray *array = @[@"yang",@"she",@"bing"];NSLog(@"%@",array[3]); </br><br />命令輸入:<br />image lookup --address 0x0000000104c25550 </br><br />輸出:<br />Address: 控制臺(tái)調(diào)試[0x000000010000145a] (控制臺(tái)調(diào)試.__TEXT.__text + 1178) </br>Summary: 控制臺(tái)調(diào)試 </br>-[ViewController touchesBegan:withEvent:] + 1178 at ViewController.m:43 </br><br /> 重點(diǎn)代碼:<br />image lookup --address
|
斷點(diǎn)輸出命令-OK.gif
- 補(bǔ)充:命令
image
- 問題:命令
image
,如何來尋找棧地址對(duì)應(yīng)代碼具體位置?(根據(jù)地址找到類中的位置,如行標(biāo)line
)
- 問題:命令
- 例如: 應(yīng)用場景(數(shù)組越界)模擬代碼:
NSArray *array = @[@"yang",@"she",@"bing"];
NSLog(@"%@",array[3]);
錯(cuò)誤信息如下:
2017-03-31 18:17:24.200 控制臺(tái)調(diào)試[21406:433320] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 3 beyond bounds [0 .. 2]'
*** First throw call stack:
(
0 CoreFoundation 0x000000010f86ed4b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010f2d021e objc_exception_throw + 48
2 CoreFoundation 0x000000010f7a92bb -[__NSArrayI objectAtIndex:] + 155
3 êé??à??è∞?∞é??? 0x000000010ecfb44a -[ViewController touchesBegan:withEvent:] + 1178
4 UIKit 0x000000010fea9f6b forwardTouchMethod + 348
5 UIKit 0x000000010fea9dfe -[UIResponder touchesBegan:withEvent:] + 49
6 UIKit 0x000000010fd02285 -[UIWindow _sendTouchesForEvent:] + 2043
7 UIKit 0x000000010fd03c33 -[UIWindow sendEvent:] + 4011
8 UIKit 0x000000010fcb09ab -[UIApplication sendEvent:] + 371
9 UIKit 0x000000011049d72d __dispatchPreprocessedEventFromEventQueue + 3248
10 UIKit 0x0000000110496463 __handleEventQueue + 4879
11 CoreFoundation 0x000000010f813761 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
12 CoreFoundation 0x000000010f7f898c __CFRunLoopDoSources0 + 556
13 CoreFoundation 0x000000010f7f7e76 __CFRunLoopRun + 918
14 CoreFoundation 0x000000010f7f7884 CFRunLoopRunSpecific + 420
15 GraphicsServices 0x000000011365aa6f GSEventRunModal + 161
16 UIKit 0x000000010fc92c68 UIApplicationMain + 159
17 êé??à??è∞?∞é??? 0x000000010ecfb83f main + 111
18 libdyld.dylib 0x00000001126d068d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
這個(gè)時(shí)候我們?nèi)绻麘岩沙鲥e(cuò)的地址是0x000000010ecfb44a
,那么我們可以使用下面命令來找出錯(cuò)誤代碼的位置:
image lookup --address 0x000000010ecfb44a
執(zhí)行命令后輸出結(jié)果如下:
(lldb) image lookup --address 0x000000010ecfb44a
Address: 控制臺(tái)調(diào)試[0x000000010000144a] (控制臺(tái)調(diào)試.__TEXT.__text + 1178)
Summary: 控制臺(tái)調(diào)試`-[ViewController touchesBegan:withEvent:] + 1178 at ViewController.m:43
斷點(diǎn)輸出命令-崩潰.gif
- 結(jié)果分析:從上面輸出結(jié)果中可以看出,錯(cuò)誤位置應(yīng)該是
ViewController.m
文件中的第43
行。 -
鏈接: