由UISearchBar引起的lldb調試

       iOS6,7中UISearchBar內部的view佈局已經完全不一樣。如圖:

wKiom1MCAmng22VDAAFAwU4sCbc798.jpg


wKioL1MCAnvgD8w3AAIFxUmmbiw250.jpg

       

上面是iOS6的,下面是iOS7的,對應的去除UISearchBar的背景色和添加其中的UITextField的代碼也不一樣。如下:

//搜索框
UISearchBar *sBar = [[UISearchBar alloc] initWithFrame:CGRectMake(83, 6, 230, 31)];
sBar.placeholder = @"請選擇類型後輸入關鍵字";
sBar.delegate = self;
sBar.barStyle = UIBarStyleDefault;
if ([sBar respondsToSelector:@selector(barTintColor)]) {
    [sBar setBarTintColor:[UIColor clearColor]];
    UIView *searchview = [sBar.subviews objectAtIndex:0];
    for (UIView *view in searchview.subviews){
        if ([view isKindOfClass: [UITextField class]]) {
            UITextField *tf = (UITextField *)view;
            tf.clearButtonMode = UITextFieldViewModeWhileEditing;
            tf.borderStyle = UITextBorderStyleNone;
            tf.background = [[UIImage imageNamed:@"bg_searchbox.png"] stretchableImageWithLeftCapWidth:20 topCapHeight:0];
            tf.leftView = nil;
            break;
        }
    }
                                                                                                                                                                  
    [_typeBtn setImageEdgeInsets:UIEdgeInsetsMake(0, 2, 0, -65)];
}
else{
    [[sBar.subviews objectAtIndex:0] removeFromSuperview];
    [sBar setBackgroundColor:[UIColor clearColor]];
                                                                                                                                                                  
    for (UIView *view in sBar.subviews){
        if ([view isKindOfClass: [UITextField class]]) {
            UITextField *tf = (UITextField *)view;
            tf.clearButtonMode = UITextFieldViewModeWhileEditing;
            tf.borderStyle = UITextBorderStyleNone;
            tf.background = [[UIImage imageNamed:@"bg_searchbox.png"] stretchableImageWithLeftCapWidth:20 topCapHeight:0];
            tf.leftView = nil;
            break;
        }
    }
}
_searchBar = [sBar retain];
[self.view addSubview:sBar];
[sBar release];


事情到這裏,公司的任務就算結束了。這個要多問一句了。圖片中的數據哪裏來的?這纔是重點。


      玩過Linux c/c++的人都知道gdb,雖然你可能完全沒有用過,好吧,我承認,我也沒正經用過,只是偶爾看到而已。iOS以前也是用gcc/gdb的,後來改用了llvm/lldb,但是大同小異了。只是這麼大的程序的到底怎麼玩調試,我還不知道,哪裏去輸入,我查了半天才找到,其實挺簡單,只要你斷點打上,在輸出log的那個區域可以直接輸入的。

     網上一哥們寫的 Xcode LLDB Debug教程,我抄在這裏:

開胃小菜--簡單的斷點調試

在xcode中打開一個app,在想要break的行號上單擊,即可生成一個深色的箭頭標識--斷點。如下圖,在viewDidLoad:中設置了斷點。235200_c3yR_724414.png

運行app,等待。。。就可以看到xcode在斷點處進入調試模式,現在讓我們把視線移到xcode右下角的控制檯,有木有看到(lldb)這樣一行,鼠標移到此行,輸入

1po [self view]
回車,看看控制檯上是不是多了一些view的信息,如下圖:235723_q6Ow_724414.png

po(print object)是LLDB的一個命令,其主要功能是輸出objective-c中對象(objects)的信息,與之相似的另外一個命令是 p(print),其主要功能是輸出原生類型(boolean、integer、float、etc)的信息。

控制檯輸入

p (int)[[[self view] subviews] count]
結果如下

(int) $2 = 2

注意這個使用了類型轉換告知調試器應該如何處理返回值。

技巧一:運行時修改變量的值

你以前怎麼驗證是不是某個變量的值導致整段程序不能正常工作?修改代碼中的變量的值,然後cmd+r重新啓動app?現在你不需要這麼做了,只需要設置一個斷點,當程序在這進入調試模式後,使用expr命令即可在運行時修改變量的值。

假如有一個loginWithUsername:方法,需要兩個參數:username,password。

首先設置好斷點,如下圖所示:

230128_xFae_724414.png

運行app,進入斷點模式後,在(lldb)後輸入

1expr username = @"username"
2expr password = @"badpassword"
控制檯會返回以下信息


1(NSString *) $0 = 0x3d3504c4 @"username"
2(NSString *) $1 = 0x1d18ef60 @"badpassword"
現在跳出斷點,執行斷點之後的兩條輸出語句,控制檯會有以下輸出


1(0x1c59aae0) A line forthe breakpoint
2(0x1c59aae0) Username and Password after: username:badpassword
看到看吧,我們在運行時修改了變量的值,事情還可以變的更簡單一些,我們可以編輯斷點,讓它自動填充需要的修改的變量的值,並且可以選擇在此斷點處不進入斷點模式,僅僅修改指定變量的值,然後自動執行後續代碼。


右擊斷點選擇“Edit Breakpoint...”(或者按住cmd+option,單擊斷點),然後如下圖所示設置斷點

231442_eqyO_724414.png

注意選中了最後一行(“Automatically continue after evaluating”)的選擇框,這就保證運行到這個斷點的時,填充變量的值,然後繼續運行,並不在此處斷點進入調試模式。

運行app,你會得到和上述手動設置變量的值一樣的輸出。

接下來單擊斷點,使其處於禁用狀態,現在箭頭的顏色應該是淺藍色的,重新運行app,你會發現username和password的值沒有在運行時被改變了。

技巧二:設置斷點觸發條件

斷點的另外一個重要作用,是可以設置觸發斷點生效的條件,這樣我們就可以在運行時針對特定的數據進行分析,觀察app是否運行在正確的軌道上。如下圖:

232822_rEBO_724414.png

上述截圖可以看到如下語句


1(BOOL)[(NSString*)[item valueForKey:@"ID"] isEqualToString:@"93306"]
通過這行語句,我們告訴編譯器:當item中ID等於93306時,此斷點生效,進入斷點調試模式。


技巧三:格式化輸出數據

如果你厭倦了代碼裏無窮無盡的NSLog,幸運的是我們可以在編輯斷點使其輸出格式化字符串就像平常編碼時一樣。不過有一點需要注意,平常編碼時可能會使用NSString‘s stringWithFormat:輸出格式化字符串,不過這個方法貌似在斷點中木有效果,你需要使用alloc/init形式的方法,如下:


1po [[NSString alloc] initWithFormat:@"Item index is: %d", index]
234126_4StM_724414.png


運行app,就能在控制檯看到想要的輸出啦!

簡單!強大!這就是LLDB給你的選擇,從此代碼裏可以不用再有NSLog滿天飛的情況了,代碼變得更乾淨了,心情變得更愉悅了!

LLDB還有很多強大的地方,本教程只不過揭開了它的面紗,即便如此,仍讓我們沉醉不已。



    到這裏,算是正式可以開始玩lldb調試了,官方主頁可以去查你想要額東西:http://lldb.llvm.org , l

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章