xcode各類調試手段

有6種方法,分別是:html

NO1:最多見,也就是NSLog

從NSLog打印出的任何東西都會變成代碼,任何人均可以看見。將設備鏈接到電腦,打開XCode中的organizer,就能夠從console查看到每條日誌信息,這會帶來很大的影響。想一下,你想把一些保密的算法邏輯或者用戶密碼打印到console。正由於這個,若是蘋果發如今項目發佈中,有太多內容輸出到console,那麼你的應用可能會遭到蘋果的拒絕。python

幸運的是,這裏有一個最簡單的辦法進行log——經過一個宏,讓NSLog只在 項目調試的時候起做用。將這個功能添加到全局都能訪問獲得的頭文件中。這樣你就能夠盡情的使用log了,而且當進行 項目發佈時,不會包含log相關代碼。以下代碼:
 
1.#ifdef DEBUG
2.#define DMLog(...) NSLog(@"%s %@", __PRETTY_FUNCTION__, [NSString stringWithFormat:__VA_ARGS__])
3.#else
4.#define DMLog(...) do { } while (0)
 
若是你使用DMLog,那麼它只能在 項目調試期間打印。__PRETTY_FUNCTION__ 也能夠幫忙打印出log所在的函數的名稱。
另外在使用NSLog的時候應當注意,release版本中應該要去掉NSLog。
 

NO2:Enable NSZombie Objects (開啓殭屍對象)--EXC_BAD_ACCESS

 NSZombieEnabled變量用來調試與內存有關的問題,跟蹤對象的釋放過程。啓用了NSZombieEnabled的話,它會用一個殭屍來替換默認的dealloc實現,也就是在引用計數降到0時,該殭屍實現會將該對象轉換成殭屍對象。殭屍對象的做用是在你向它發送消息時,它會顯示一段日誌並自動跳入調試器。ios

          因此,當在應用中啓用NSZombie而不是讓應用直接崩潰掉時,一個錯誤的內存訪問就會變成一條沒法識別的消息發送給殭屍對象。殭屍對象會顯示接受到得信息,而後跳入調試器,這樣你就能夠查看究竟是哪裏出了問題。git

         能夠在Xcode的scheme頁面中設置NSZombieEnabled環境變量。點擊Product——>Edit Scheme打開該頁面,而後勾選Enable Zombie Objects 複選框。github

 

而後選中下圖中的選項算法

 Zombie模式不能再真機上使用,只能在模擬器上使用express

NO3:斷點調試(全局斷點、條件斷點、符號斷點)

1、全局斷點(異常斷點):異常斷點能夠快速定位不知足特定條件的異常,好比常見的數組越界,這時候很難經過異常信息定位到錯誤所在位置。這個時候異常斷點就能夠發揮做用了。小程序

NSArray *aa = @[@2,@4];
NSLog(@"%@",aa[3]);

 這兩行代碼,沒有添加全局斷點時,運行crash,直接就跳到了mian函數,以下圖:數組

接下來添加全局斷點,方法以下圖:框架

點擊了Exception BreakPoint 後

添加以後運行,奔潰後,程序停留在了奔潰的那行代碼。

 

Exception:能夠選擇拋出異常對象類型:OC或C++。

Break:選擇斷點接收的拋出異常來源是Throw仍是Catch語句。

 

ps 不過有時候程序奔潰,這種方式定位不到

 

2、條件斷點:設置斷點觸發的條件,方便開發者對特定狀況進行調試

添加(刪除)條件斷點的快捷鍵:command+\

以下圖:

在for循環中添加一個斷點。右擊斷點選擇」Edit BreakPoint」,而後設置斷點觸發條件。

這個例子當 「i==5」時,斷點觸發,以下圖:

 

 

3、符號斷點:

 

選擇Symbolic Breakpoint後

例如:unrecognized selector send to instancd 的快速定位

NO4:

 

設置完成後再遇到相似的錯誤就會定位到具體的代碼

NO4:Static Analyzer (靜態分析)

Static Analyzer主要用於分析內存,避免內存泄漏。主要對如下狀況進行分析。 
未使用的實例變量、未初始化的實例變量、類型不兼容、沒法達到的路徑、引用空指針 
使用快捷鍵:command + shift +B,能夠去以下圖中去設置

以下圖就能輕鬆找到可能內存泄漏的代碼,而後咱們根據代碼環境進行修復就能夠了

 

(ps:有的內存泄漏可能檢測不出來,仍是須要咱們在寫代碼時對內存這塊多留點心。)

 

NO5:Address Sanitizer

在Xcode7以後新增了AddressSanitizer工具,爲咱們調試EXC_BAD_ACCESS錯誤提供了便利。當程序建立變量分配一段內存時,將此內存後面的一段內存也凍結住,標識爲中毒內存。程序訪問到中毒內存時(訪問越界),當即中斷程序,拋出異常並打印異常信息。你能夠根據中斷位置及輸出的Log信息來解決錯誤。固然,若是變量已經釋放了,它所佔用的內存也會被標識爲中毒內存,這個時候訪問這片內存空間一樣會拋出異常。

使用方法:

「Edit Scheme…」 —> 「Run」 —> 「Diagnostics」 —> 「Zombie Objects」

 

 

開啓AddressSanitizer以後,在調試程序的過程當中,若是有遇到EXC_BAD_ACCESS錯誤,程序則會自動終止,拋出異常。

 

NO6:LLDB調試器

LLDB是一個有着 REPL 的特性和 C++ ,Python 插件的開源調試器。LLDB 綁定在 Xcode 內部,存在於主窗口底部的控制檯中。調試器容許你在程序運行的特定時暫停它,你能夠查看變量的值,執行自定的指令,而且按照你所認爲合適的步驟來操做程序的進展。(這裏有一個關於調試器如何工做的整體的解釋。)

你之前有可能已經使用過調試器,即便只是在 Xcode 的界面上加一些斷點。可是經過一些小的技巧,你就能夠作一些很是酷的事情。GDB to LLDB 參考是一個很是好的調試器可用命令的總覽。你也能夠安裝 Chisel,它是一個開源的 LLDB 插件合輯,這會使調試變得更加有趣。

與此同時,讓咱們以在調試器中打印變量來開始咱們的旅程吧。

基礎

這裏有一個簡單的小程序,它會打印一個字符串。注意斷點已經被加在第 8 行。斷點能夠經過點擊 Xcode 的源碼窗口的側邊槽進行建立。

1.png

程序會在這一行中止運行,而且控制檯會被打開,容許咱們和調試器交互。那咱們應該打些什麼呢?

help

最簡單命令是 help,它會列舉出全部的命令。若是你忘記了一個命令是作什麼的,或者想知道更多的話,你能夠經過 help來了解更多細節,例如 help print 或者 help thread。若是你甚至忘記了 help 命令是作什麼的,你能夠試試 help help。不過你若是知道這麼作,那就說明你大概尚未忘光這個命令。??

print

打印值很簡單;只要試試 print 命令:

2.png

LLDB 實際上會做前綴匹配。因此你也可使用 prin,pri,或者 p。但你不能使用 pr,由於 LLDB 不能消除和 process 的歧義 (幸運的是 p 並無歧義)。

你可能還注意到了,結果中有個 $0。實際上你可使用它來指向這個結果。試試 print $0 + 7,你會看到 106。任何以美圓符開頭的東西都是存在於 LLDB 的命名空間的,它們是爲了幫助你進行調試而存在的。

expression

若是想改變一個值怎麼辦?你或許會猜 modify。其實這時候咱們要用到的是 expression 這個方便的命令。

這不只會改變調試器中的值,實際上它改變了程序中的值。這時候繼續執行程序,將會打印 42 red balloons。神奇吧。

注意,從如今開始,咱們將會偷懶分別以 p 和 e 來代替 print 和 expression。

什麼是 print 命令

考慮一個有意思的表達式:p count = 18。若是咱們運行這條命令,而後打印 count 的內容。咱們將看到它的結果與 expression count = 18 同樣。

和 expression 不一樣的是,print 命令不須要參數。好比 e -h +17 中,你很難區分究竟是以 -h 爲標識,僅僅執行 +17 呢,仍是要計算 17 和 h 的差值。連字符號確實很讓人困惑,你或許得不到本身想要的結果。

幸運的是,解決方案很簡單。用 -- 來表徵標識的結束,以及輸入的開始。若是想要 -h 做爲標識,就用 e -h -- +17,若是想計算它們的差值,就使用 e -- -h +17。由於通常來講不使用標識的狀況比較多,因此 e -- 就有了一個簡寫的方式,那就是 print。

輸入 help print,而後向下滾動,你會發現:

1
2
'print'  is an abbreviation  for  'expression --' .   
(print是 `expression --` 的縮寫)

打印對象

嘗試輸入

1
p objects

輸出會有點囉嗦

1
(NSString *) $7 = 0x0000000104da4040 @ "red balloons"

若是咱們嘗試打印結構更復雜的對象,結果甚至會更糟

1
2
(lldb) p @[ @ "foo" , @ "bar"  ]
(NSArray *) $8 = 0x00007fdb9b71b3e0 @ "2 objects"

實際上,咱們想看的是對象的 description 方法的結果。我麼須要使用 -O (字母 O,而不是數字 0) 標誌告訴 expression 命令以 對象 (Object) 的方式來打印結果。

1
2
3
4
(lldb) e -O -- $8(
foo,
bar
)

幸運的是,e -o -- 有也有個別名,那就是 po (print object 的縮寫),咱們可使用它來進行簡化:

1
2
3
4
5
6
7
8
(lldb) po $8(
foo,
bar
)
(lldb) po @ "lunar"
lunar
(lldb) p @ "lunar"
(NSString *) $13 = 0x00007fdb9d0003b0 @ "lunar"

打印變量

能夠給 print 指定不一樣的打印格式。它們都是以 print/或者簡化的 p/格式書寫。下面是一些例子:

默認的格式

1
2
(lldb) p 16
16

十六進制:

1
2
(lldb) p/x 16
0x10

二進制 (t 表明 two):

1
2
3
4
(lldb) p/t 16
0b00000000000000000000000000010000
(lldb) p/t (char)16
0b00010000

你也可使用 p/c 打印字符,或者 p/s 打印以空終止的字符串 (譯者注:以 '\0' 結尾的字符串)。 

這裏是格式的完整清單。

變量

如今你已經能夠打印對象和簡單類型,而且知道如何使用 expression 命令在調試器中修改它們了。如今讓咱們使用一些變量來減小輸入量。就像你能夠在 C 語言中用 int a = 0 來聲明一個變量同樣,你也能夠在 LLDB 中作一樣的事情。不過爲了能使用聲明的變量,變量必須以美圓符開頭。

1
2
3
4
5
6
7
8
9
10
11
(lldb) e int $a = 2
(lldb) p $a * 19
38
(lldb) e NSArray *$array = @[ @ "Saturday" , @ "Sunday" , @ "Monday"  ]
(lldb) p [$array count]
2
(lldb) po [[$array objectAtIndex:0] uppercaseString]
SATURDAY
(lldb) p [[$array objectAtIndex:$a] characterAtIndex:0]
error: no known method  '-characterAtIndex:' ; cast the message send to the method's  return  type
error: 1 errors parsing expression

悲劇了,LLDB 沒法肯定涉及的類型 (譯者注:返回的類型)。這種事情經常發生,給個說明就行了:

1
2
3
4
(lldb) p (char)[[$array objectAtIndex:$a] characterAtIndex:0]
'M'
(lldb) p/d (char)[[$array objectAtIndex:$a] characterAtIndex:0]
77

變量使調試器變的容易使用得多,想不到吧???

bt

打印調用堆棧信息,使用 bt all命令能夠打印出全部thread的調用棧信息

好比說:call [self.view setBackgroundColor:[UIColor redColor]],使用這個命令來設置view controller的背景色爲紅色

 

對中文的兼容

有中文時必須使用 [NSString stringWithUTF8String:] 方法,緣由在於lldb的expression parser有一個bug,不兼容非ASCII字符,須要處理一下才行,不然會報錯「An Objective-C constant string's string initializer is not an array」,參考:http://stackoverflow.com/questions/17192505/error-in-breakpoint-condition

類型的問題

出現類型不肯定或類型不匹配的時候,就會報錯,這個時候必須強制轉換才能夠。

好比前文中獲取indexPath的row的方法的表達式:(int)[indexPath row],或者相似下面這種乾脆無返回值 p (void)NSLog(@"%@",[self.view  viewWithTag:1001]),或者上文中的 p (char)[[$array objectAtIndex:$a] characterAtIndex:0],這些場景中都須要明確輸出的類型。

找不到方法

注意,使用系統框架對象的屬性時不能使用dot語法,好比下圖中的問題。

blob.png

blob.png改爲以下的格式才行:

blob.png

流程控制

當你經過 Xcode 的源碼編輯器的側邊槽 (或者經過下面的方法) 插入一個斷點,程序到達斷點時會就會中止運行。

調試條上會出現四個你能夠用來控制程序的執行流程的按鈕。

4.png

從左到右,四個按鈕分別是:continue,step over,step into,step out。

第一個,continue 按鈕,會取消程序的暫停,容許程序正常執行 (要麼一直執行下去,要麼到達下一個斷點)。在 LLDB 中,你可使用 process continue 命令來達到一樣的效果,它的別名爲 continue,或者也能夠縮寫爲 c。

第二個,step over 按鈕,會以黑盒的方式執行一行代碼。若是所在這行代碼是一個函數調用,那麼就不會跳進這個函數,而是會執行這個函數,而後繼續。LLDB 則可使用 thread step-over,next,或者 n 命令。

若是你確實想跳進一個函數調用來調試或者檢查程序的執行狀況,那就用第三個按鈕,step in,或者在LLDB中使用 thread step in,step,或者 s 命令。注意,當前行不是函數調用時,next 和 step 效果是同樣的。

大多數人知道 c,n 和 s,可是其實還有第四個按鈕,step out。若是你曾經不當心跳進一個函數,但實際上你想跳過它,常見的反應是重複的運行 n 直到函數返回。其實這種狀況,step out 按鈕是你的救世主。它會繼續執行到下一個返回語句 (直到一個堆棧幀結束) 而後再次中止。

例子

考慮下面一段程序:

5.png

假如咱們運行程序,讓它中止在斷點,而後執行下面一些列命令:

1
2
3
4
5
6
7
p i
n
s
p i
finish
p i
frame info

這裏,frame info 會告訴你當前的行數和源碼文件,以及其餘一些信息;查看 help frame,help thread 和 help process 來得到更多信息。這一串命令的結果會是什麼?看答案以前請先想想。

1
2
3
4
5
6
7
8
9
10
11
12
13
(lldb) p i
(int) $0 = 99
(lldb) n
2014-11-22 10:49:26.445 DebuggerDance[60182:4832768] 101 is odd!
(lldb) s
(lldb) p i
(int) $2 = 110
(lldb) finish
2014-11-22 10:49:35.978 DebuggerDance[60182:4832768] 110 is even!
(lldb) p i
(int) $4 = 99
(lldb) frame info
frame  #0: 0x000000010a53bcd4 DebuggerDance`main + 68 at main.m:17

它始終在 17 行的緣由是 finish 命令一直運行到 isEven() 函數的 return,而後馬上中止。注意即便它還在 17 行,其實這行已經被執行過了。

Thread Return

調試時,還有一個很棒的函數能夠用來控制程序流程:thread return 。它有一個可選參數,在執行時它會把可選參數加載進返回寄存器裏,而後馬上執行返回命令,跳出當前棧幀。這意味這函數剩餘的部分不會被執行。這會給 ARC 的引用計數形成一些問題,或者會使函數內的清理部分失效。可是在函數的開頭執行這個命令,是個很是好的隔離這個函數,僞造返回值的方式 。

讓咱們稍微修改一下上面代碼段並運行:

1
2
3
4
5
6
p i
s
thread  return  NO
n
p even0
frame info

看答案前思考一下。下面是答案:

1
2
3
4
5
6
7
8
9
(lldb) p i
(int) $0 = 99
(lldb) s
(lldb) thread  return  NO
(lldb) n
(lldb) p even0
(BOOL) $2 = NO
(lldb) frame info
frame  #0: 0x00000001009a5cc4 DebuggerDance`main + 52 at main.m:17

 

 

Chisel-LLDB命令插件

Chisel介紹

源碼地址:Chisel
Chisel擴展了一些列的lldb的命令來幫助iOS開發者調試iOS應用程序。

安裝Chisel

1.確保終端安裝了Homebrew

2.終端執行命令:brew install chisel  輸入命令後我遇到第一個問題。


brew install chisel 後可能出現的問題

遇見這個問題終端執行命令:sudo chown -R ${USER} /Library/Caches/Homebrew/,執行此命令後問題解決。

3.若是沒有第二步的問題,執行命令:brew install chisel後出現以下界面


brew install chisel 執行成功

4.注意看Caveats下面的那兩行,意思是把第二行的文字command script import /usr/local/opt/chisel/libexec/fblldb.py添加到.lldbinit文件中,這時執行命令echo command script import /usr/local/opt/chisel/libexec/fblldb.py >> ~/.lldbinit(粗體文字替換爲你終端Caveats下面的第二行文字)可免去你去找.lldbinit文件,或者.lldbinit文件不出現的煩惱啊。到此步不出意外已經安裝成功。

5.安裝成功後從新啓動Xcode便可。

6.終端下檢查是否安裝成功輸入命令:lldb,而後輸入help,往下翻出現以下界面爲成功


Chisel安裝成功

7.Xcode下檢查是否安裝成功,打斷點進入lldb下輸入help,往下翻出現以下界面爲成功


Chisel安裝成功後,就開始熟悉命令

2.內置命令

Chisel 爲lldb提供了新增的便捷命令,是很是實用的命令

2.1 pviews

這個命令能夠遞歸打印全部的view,並能標示層級,至關於 UIView 的私有輔助方法  [view recursiveDescription] 。 善用使用這個功能會讓你在調試定位問題時省去不少麻煩。

使用示例:

(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的結構一目瞭然。 其實蘋果在IOS8也默默的添加了 UIViewController 的一個私有輔助方法 [UIViewController _printHierarchy] 一樣的效果。

預覽效果:

(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 是否已經 viewDidLoad .

2.3 visualize

這是個頗有意思的功能,它可讓你使用Mac的預覽打開一個 UIImage, CGImageRef, UIView, 或 CALayer。 這個功能或許能夠幫咱們用來截圖、用來定位一個view的具體內容。 可是在我試用了一下,發現暫時仍是隻能在模擬器時使用,真機還不行。

使用簡單:

(lldb) visualize imageView

 

2.4 fv & fvc

fv 和 fvc 這兩個命令是用來經過類名搜索當前內存中存在的view和viewController實例的命令,支持正則搜索。

如:

(lldb) fv scrollView
0x18d3b8c0 UIScrollView
0x137d0c50 UIScrollView
0x131b1580 UIScrollView
0x131b2070 UIScrollView
(lldb) fvc Home
0x1393fe00 HomeFeedsViewController
0x138a8e00 HomeFeedsViewController
(lldb)

 

2.5 show & hide

這兩個命令用來顯示和隱藏一個指定的 UIView . 

   (lldb) show self.view
   (lldb) hide  self.view

 也可使用內存地址隱藏和現實view,好比經過 fv cate找到一個view後使用hide隱藏它

(lldb)fv cate
    0x7fd5b6e06920 AlbumCategoryView

 (lldb) hide  0x7fd5b6e06920

 

2.6 mask/umask border/unborder

這兩組命令用來標識一個view或layer的位置時用, mask用來在view上覆蓋一個半透明的矩形, border能夠給view添加邊框。可是在我實際使用的過程當中mask老是會報錯,估計是有bug, 那麼mask/unmask 通常不要用好了,用border命令是同樣的效果,反正兩者的用途都是找到一個對應的view.

若是我要給第二個view添加一個顏色爲藍色,寬度爲2的邊框,以後再用unborder命令移除,操做以下:

經過help border命令知道border的使用格式以下:

Options:
--color/-c <color>; Type: string; A color name such as 'red', 'green',
 'magenta', etc.
 --width/-w <width>; Type: CGFloat; Desired width of border.
Syntax: border [--color=color] [--width=width] <viewOrLayer>

 

其中viewOrLayer表示你要修改的view的地址,咱們經過pviews命令知道,第二個view的地址是0x7feae2d605f0,因此咱們輸入

border -c blue -w 2 0x7feae2d605f0  //添加邊框
unborder 0x7feae2d605f0   //移除邊框

 注意我在輸入每一個border/unborder命令時,右側模擬器第二個view(紅色view)的變化。

2.7 caflush

這個命令會從新渲染,便可以從新繪製界面, 至關於執行了 [CATransaction flush] 方法,要注意若是在動畫過程當中執行這個命令,就直接渲染出動畫結束的效果。

當你想在調試界面顏色、座標之類的時候,能夠直接在控制檯修改屬性,而後caflush就能夠看到效果啦,是否是要比改代碼,而後從新build省事多了呢。

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

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

 

2.8 bmessage

這個命令就是用來打斷點用的了,雖然你們斷點可能都喜歡在圖形界面裏面打,可是考慮一種狀況:咱們想在 [MyViewController viewWillAppear:] 裏面打斷點,可是 MyViewController並無實現 viewWillAppear: 方法, 以往的做法可能就是在子類中實現下viewWillAppear:,而後打斷點,而後rebuild。

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

3. 自定義命令

咱們也能夠自定義插件,不過前提是要懂一些 python。 好比設計一個打印keyWindow的windowLevel的命令:

建立python腳本文件 /magical/commands/example.py :

#!/usr/bin/python
# Example file with custom commands, located at /magical/commands/example.py

import lldb
import fblldbbase as fb

def 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的類,須要實現 name description run 方法來分別告訴名稱、描述、和執行實體。

建立好腳本後,而後在前面安裝時建立的 ~/.lldbinit文件中添加一行:

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

 

而後重啓Xcode以後就可使用自定義的命令啦。

 

 

參考連接:

http://www.jianshu.com/p/79468a2eb6db

https://blog.cnbluebox.com/blog/2015/03/05/chisel/

http://www.cocoachina.com/ios/20141219/10709.html

http://www.jianshu.com/p/3e4b10083b4d

http://www.cocoachina.com/ios/20150803/12805.html

http://www.cocoachina.com/ios/20161102/17884.html

http://blog.csdn.net/u013822374/article/details/50963108

http://www.cocoachina.com/ios/20130517/6225.html

http://www.cocoachina.com/ios/20140526/8555.html

相關文章
相關標籤/搜索