Xcode 斷點調試

轉自:https://www.leewong.cn/2020/07/25/howtousexcodebreakpoint/

上圖是我們使用Xcode進行斷點調試時,上圖底部圖標從左到右功能分別如下:

  • 啟用/禁用斷點(點擊后變灰色,所有斷點失效;再點擊變藍色,所有斷點生效)
  • 繼續執行程序(點擊后跳過本次斷點,繼續執行程序)
  • 執行下一步(點擊后執行第23行代碼)
  • 進入方法(點擊后進入-testLog方法)
  • 跳出方法(在-testLog方法內部點擊后回到第22行代碼)

除了這些功能,我們還可以編輯斷點,在斷點出右鍵選擇Edit BreakPoint

下面我們來分別介紹下這幾個選項以及如何設置這些選項:

Condition

Condition 表示斷點條件。開發者可以在 Condition 輸入框中設置觸發斷點的條件。比如上面 for 循環的例子我們可以在 Condition 條件中添加條件

這樣我們的斷點只有在index==5時才會被觸發,這樣就有利于我們在某些for循環時只有在滿足某個條件時才觸發斷點。

Ignore

Ignore為忽略次數,同樣我們在上面for循環的例子中可以將Ignore設置為5,那么斷點第一次觸發時index=6時。

Action

Action為觸發動作。Action可以添加多條,在觸發斷點后,會緊接著執行設定的Actions。Action有6種執行類型,其中較常用的有Debugger Command和Log message。

Debugger Command

Log Message

當然log的信息還可以讀出來

試一下吧,有驚喜!!!

Options

Options控制在執行斷點對應的Actions后是否自動繼續執行程序。勾選后Options后,斷點被觸發后不進入Debug界面。

接下來看下斷點的正題

斷點

斷點類型

我們在Xocde中添加斷點時有幾種類型的斷點:

下面介紹下常用的幾種類型的斷點:

Exception Breakpoint(異常斷點)

當我們添加了一個Exception BreakPoint時,實際上是添加了一個全局斷點

正常情況下我們的代碼崩潰后,如果沒有全局斷點 代碼會崩潰在main函數中,但是我們如果添加了全局斷點,代碼發生崩潰時,就會自動崩潰到出現問題的哪一行代碼,比較方便我們去定位問題。

Symbolic Breakpoint (符號斷點)

當我們添加一個符號斷點時,會自動為我們彈出自定義面板,

與普通斷點相比,符號斷點的編輯界面多出來Symbol和Module兩個輸入框。下面我們來看下這兩個輸入框的作用。

Symbol

可以在Symbol輸入框中設置斷點觸發方法/函數。在Symbol中設置一個方法/函數后,運行程序并執行到此方法時會觸發斷點。

如果是C語言方法那么直接使用方法名就可以

Module

可以在Module輸入框中設置Symbol中的函數所在的庫,以避免不同庫中存在名字相同的方法/函數,默認不用填寫。

Condition

與普通斷點的用法基本一致
在Condition輸入框中設置$arg3==nil,就會限制斷點在滿足第一個參數和第二個參數都為nil時才會被觸發。但是實際上使用下面這種寫法才可以
[(NSString *)$arg3 length] == 0

這里我們可以用來判斷某個方法再被調用時,哪里的參數傳遞是有問題的。

Watch Breakpoint(監控斷點)

有時候我們需要監聽某個變量的值的變化

添加斷點


斷點結果
image

很可惜沒有發現監聽數組個數變化的斷點

斷點的應用

查看UI控件約束沖突

我們先看下下面這段代碼:

- (void)addVCSubView {
    UIView *contentView = [[UIView alloc] init];
    contentView.backgroundColor = [UIColor blueColor];
    [self.view addSubview:contentView];
    [contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self.view);
        make.width.height.equalTo(@200);
    }];


    UIView *view = [[UIView alloc] init];
    view.backgroundColor = [UIColor greenColor];
    [contentView addSubview:view];
    [view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.centerX.equalTo(contentView);
        make.centerY.equalTo(contentView);
        make.top.equalTo(contentView.mas_top).offset(20);
        make.width.height.equalTo(@100);
    }];
}
- (void)addVCSubView {    UIView *contentView = [[UIView alloc] init];    contentView.backgroundColor = [UIColor blueColor];    [self.view addSubview:contentView];    [contentView mas_makeConstraints:^(MASConstraintMaker *make) {        make.center.equalTo(self.view);        make.width.height.equalTo(@200);    }];    UIView *view = [[UIView alloc] init];    view.backgroundColor = [UIColor greenColor];    [contentView addSubview:view];    [view mas_makeConstraints:^(MASConstraintMaker *make) {        make.centerX.equalTo(contentView);        make.centerY.equalTo(contentView);        make.top.equalTo(contentView.mas_top).offset(20);        make.width.height.equalTo(@100);    }];}

具體的展示如圖:

從圖中我們可以很明顯的看到綠色的子視圖的寬高并不相同,同樣在控制臺上我們也看到了這樣的輸出

[LayoutConstraints] Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<MASLayoutConstraint:0x600000e183c0 UIView:0x7fa513e11cc0.height == 200>",
    "<MASLayoutConstraint:0x600000e181e0 UIView:0x7fa516604e70.centerY == UIView:0x7fa513e11cc0.centerY>",
    "<MASLayoutConstraint:0x600000e18600 UIView:0x7fa516604e70.top == UIView:0x7fa513e11cc0.top + 20>",
    "<MASLayoutConstraint:0x600000e186c0 UIView:0x7fa516604e70.height == 100>"
)

Will attempt to recover by breaking constraint 
<MASLayoutConstraint:0x600000e186c0 UIView:0x7fa516604e70.height == 100>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.

控制臺提示我們 下面列表中的約束其中有一個是不需要的,同時當前展示的樣子是系統通過移除了哪個約束后展示出來的

約束問題是什么

我們先看下控制臺輸出的提示

"<MASLayoutConstraint:0x600000e183c0 UIView:0x7fa513e11cc0.height == 200>",
"<MASLayoutConstraint:0x600000e181e0 UIView:0x7fa516604e70.centerY == UIView:0x7fa513e11cc0.centerY>",
"<MASLayoutConstraint:0x600000e18600 UIView:0x7fa516604e70.top == UIView:0x7fa513e11cc0.top + 20>",
"<MASLayoutConstraint:0x600000e186c0 UIView:0x7fa516604e70.height == 100>"

上面的提示中設計到兩個UIView對象,0x600000e183c00x7fa513e11cc0,通過查看上面的約束提示,我們發現height,centerY,top,height 這幾個約束都是垂直方向的約束。

上面的提示還有下面這句

Will attempt to recover by breaking constraint 
<MASLayoutConstraint:0x600000e186c0 UIView:0x7fa516604e70.height == 100>

嘗試通過break高度為100的約束來正確展示這個視圖,而結合我們上面展示的圖片 沒有生效的約束是height=100與上面的描述一致。

那通過上面的分析我們得出這次約束的問題是:

控件0x600000e183c00x7fa516604e70在垂直方向存在約束沖突,目前系統通過移除UIView:0x7fa516604e70.height == 100約束來展示UI,如果系統的修改與你的預期不符,可以通過修改上面提到的四個約束中的一個來展示出正確的UI。

哪個視圖約束有問題

分析出約束的問題后,我們需要定位到底是哪兩個視圖出現了約束問題。

通過內存地址定位

我們可以通過查看層次結果,然后通過出現約束問題的視圖的內存地址進行篩選,這樣我們就能容易的定位到出現問題的視圖。

通過lldb命令

我們還可以通過設置出現問題的視圖的背景顏色來定位到底是哪個視圖出現問題,當然是用lldb命令的前提是我們需要在合適的地方添加斷點。

首先我們需要在項目中添加約束沖突(符號斷點)斷點,添加方法如下

添加了這個斷點后,在應用啟動遇到約束沖突的位置系統會,直接有約束沖突的位置設置斷點,下面截取一部分發生斷點時的提示

*UIButton:0x10b091670'注冊/登錄'- AMBIGUOUS LAYOUT for UIButton:0x10b091670'注冊/登錄'.minY{id: 159}   UIButtonLabel:0x10b15fb60'注冊/登錄'

 *UILabel:0x10b08f790'群組'- AMBIGUOUS LAYOUT for UILabel:0x10b08f790'群組'.minX{id: 136}, UILabel:0x10b08f790'群組'.minY{id: 138}, UILabel:0x10b08f790'群組'.Width{id: 135}, UILabel:0x10b08f790'群組'.Height{id: 140}

這里我們可以通過關鍵詞 AMBIGUOUS LAYOUT 來獲取所有存在約束沖突的位置,因為log中有了按鈕或者label的文案我們可以很快的定位到具體位置。
當然 如果層次非常深,或者我們無法通過文案進行區分,我們還可以通過下面的命令修改視圖的背景顏色來定位出現約束沖突的視圖。

expr ((UILabel *)0x10b091670).backgroundColor = [UIColor yellowColor];

結果如下圖:

通過上面的方法我們可以定位到出現問題的視圖控件,那么我們 下一步就要看如何去解決這個約束沖突。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容