轉(zhuǎn)自:https://www.leewong.cn/2020/07/25/howtousexcodebreakpoint/
上圖是我們使用Xcode進行斷點調(diào)試時侥祭,上圖底部圖標從左到右功能分別如下:
- 啟用/禁用斷點(點擊后變灰色,所有斷點失效;再點擊變藍色,所有斷點生效)
- 繼續(xù)執(zhí)行程序(點擊后跳過本次斷點,繼續(xù)執(zhí)行程序)
- 執(zhí)行下一步(點擊后執(zhí)行第23行代碼)
- 進入方法(點擊后進入-testLog方法)
- 跳出方法(在-testLog方法內(nèi)部點擊后回到第22行代碼)
除了這些功能既鞠,我們還可以編輯斷點,在斷點出右鍵選擇Edit BreakPoint
下面我們來分別介紹下這幾個選項以及如何設(shè)置這些選項:
Condition
Condition
表示斷點條件。開發(fā)者可以在 Condition
輸入框中設(shè)置觸發(fā)斷點的條件链方。比如上面 for 循環(huán)的例子我們可以在 Condition
條件中添加條件
這樣我們的斷點只有在index==5
時才會被觸發(fā),這樣就有利于我們在某些for循環(huán)時只有在滿足某個條件時才觸發(fā)斷點。
Ignore
Ignore
為忽略次數(shù),同樣我們在上面for循環(huán)的例子中可以將Ignore
設(shè)置為5灶搜,那么斷點第一次觸發(fā)時index=6時祟蚀。
Action
Action為觸發(fā)動作。Action可以添加多條占调,在觸發(fā)斷點后暂题,會緊接著執(zhí)行設(shè)定的Actions。Action有6種執(zhí)行類型究珊,其中較常用的有Debugger Command和Log message薪者。
Debugger Command
Log Message
當然log的信息還可以讀出來
試一下吧,有驚喜=虽獭Q越颉!
Options
Options
控制在執(zhí)行斷點對應(yīng)的Actions
后是否自動繼續(xù)執(zhí)行程序取试。勾選后Options
后悬槽,斷點被觸發(fā)后不進入Debug
界面。
接下來看下斷點的正題
斷點
斷點類型
我們在Xocde中添加斷點時有幾種類型的斷點:
下面介紹下常用的幾種類型的斷點:
Exception Breakpoint(異常斷點)
當我們添加了一個Exception BreakPoint
時瞬浓,實際上是添加了一個全局斷點
正常情況下我們的代碼崩潰后初婆,如果沒有全局斷點 代碼會崩潰在main函數(shù)中,但是我們?nèi)绻砑恿巳謹帱c猿棉,代碼發(fā)生崩潰時磅叛,就會自動崩潰到出現(xiàn)問題的哪一行代碼,比較方便我們?nèi)ザㄎ粏栴}萨赁。
Symbolic Breakpoint (符號斷點)
當我們添加一個符號斷點時弊琴,會自動為我們彈出自定義面板,
與普通斷點相比杖爽,符號斷點的編輯界面多出來Symbol和Module兩個輸入框敲董。下面我們來看下這兩個輸入框的作用紫皇。
Symbol
可以在Symbol輸入框中設(shè)置斷點觸發(fā)方法/函數(shù)。在Symbol中設(shè)置一個方法/函數(shù)后腋寨,運行程序并執(zhí)行到此方法時會觸發(fā)斷點聪铺。
如果是C語言方法那么直接使用方法名就可以
Module
可以在Module輸入框中設(shè)置Symbol中的函數(shù)所在的庫,以避免不同庫中存在名字相同的方法/函數(shù)萄窜,默認不用填寫计寇。
Condition
與普通斷點的用法基本一致
在Condition輸入框中設(shè)置$arg3==nil
,就會限制斷點在滿足第一個參數(shù)和第二個參數(shù)都為nil時才會被觸發(fā)脂倦。但是實際上使用下面這種寫法才可以
[(NSString *)$arg3 length] == 0
這里我們可以用來判斷某個方法再被調(diào)用時番宁,哪里的參數(shù)傳遞是有問題的。
Watch Breakpoint(監(jiān)控斷點)
有時候我們需要監(jiān)聽某個變量的值的變化
斷點結(jié)果
很可惜沒有發(fā)現(xiàn)監(jiān)聽數(shù)組個數(shù)變化的斷點
斷點的應(yīng)用
查看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.
控制臺提示我們 下面列表中的約束其中有一個是不需要的蝶押,同時當前展示的樣子是系統(tǒng)通過移除了哪個約束后展示出來的
約束問題是什么
我們先看下控制臺輸出的提示
"<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>"
上面的提示中設(shè)計到兩個UIView對象,0x600000e183c0
和0x7fa513e11cc0
,通過查看上面的約束提示火欧,我們發(fā)現(xiàn)height
,centerY
,top
,height
這幾個約束都是垂直方向的約束棋电。
上面的提示還有下面這句
Will attempt to recover by breaking constraint
<MASLayoutConstraint:0x600000e186c0 UIView:0x7fa516604e70.height == 100>
嘗試通過break高度為100的約束來正確展示這個視圖,而結(jié)合我們上面展示的圖片 沒有生效的約束是height=100
與上面的描述一致苇侵。
那通過上面的分析我們得出這次約束的問題是:
控件0x600000e183c0
和0x7fa516604e70
在垂直方向存在約束沖突赶盔,目前系統(tǒng)通過移除UIView:0x7fa516604e70.height == 100
約束來展示UI,如果系統(tǒng)的修改與你的預(yù)期不符榆浓,可以通過修改上面提到的四個約束中的一個來展示出正確的UI于未。
哪個視圖約束有問題
分析出約束的問題后,我們需要定位到底是哪兩個視圖出現(xiàn)了約束問題陡鹃。
通過內(nèi)存地址定位
我們可以通過查看層次結(jié)果烘浦,然后通過出現(xiàn)約束問題的視圖的內(nèi)存地址進行篩選,這樣我們就能容易的定位到出現(xiàn)問題的視圖萍鲸。
通過lldb命令
我們還可以通過設(shè)置出現(xiàn)問題的視圖的背景顏色來定位到底是哪個視圖出現(xiàn)問題闷叉,當然是用lldb命令的前提是我們需要在合適的地方添加斷點。
首先我們需要在項目中添加約束沖突(符號斷點)斷點脊阴,添加方法如下
添加了這個斷點后握侧,在應(yīng)用啟動遇到約束沖突的位置系統(tǒng)會,直接有約束沖突的位置設(shè)置斷點嘿期,下面截取一部分發(fā)生斷點時的提示
*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}
這里我們可以通過關(guān)鍵詞 AMBIGUOUS LAYOUT
來獲取所有存在約束沖突的位置品擎,因為log中有了按鈕或者label的文案我們可以很快的定位到具體位置。
當然 如果層次非常深秽五,或者我們無法通過文案進行區(qū)分孽查,我們還可以通過下面的命令修改視圖的背景顏色來定位出現(xiàn)約束沖突的視圖饥悴。
expr ((UILabel *)0x10b091670).backgroundColor = [UIColor yellowColor];
結(jié)果如下圖:
通過上面的方法我們可以定位到出現(xiàn)問題的視圖控件坦喘,那么我們 下一步就要看如何去解決這個約束沖突盲再。