Objective-C除錯技巧——iOS開發者的Debug指南

語言: CN / TW / HK

theme: github

前言

  開發者們在使用Objective-C開發過程中難免會遇到各種型別的bug或難題,而熟練使用IDE工具進行除錯無疑會提高開發效率,這裡我總結了常用的除錯技巧。

  接下來我會從以下幾個方面逐一介紹:首先簡單介紹Xcode除錯需要關注的工具條,這裡斷點工具條會被放入後續斷點相關的內容中;接下來會敘述專案隱藏漏洞排查“利器”——程式碼靜態分析;然後我們會將注意力集中在斷點除錯上;光有斷點還不夠,我還補充了Log的使用,在特定場景使用有意想不到的效果;作為靜態分析的對照,我簡單介紹了程式碼動態分析及其使用;最後本文會提供一些除錯相關的雜項內容當做補充。後續我會將Objecttive-C簡稱為OC。因為涉及面較廣,我更希望讀者當它是一個索引,根據目錄找到感興趣的內容,給到讀者一些思考啟發。

1 Xcode工具條熟悉

  工欲善其事必先利其器,在介紹OC除錯前,先熟悉Xcode中左上角的工具欄,後續內容會重點關注紅框標註出的四個部分。 - 專案導航器(Project navigator):管理專案中的檔案資源; - 版本控制導航器(Source Control navigator):檢視分支檔案修改情況以及專案倉庫資訊,如分支名、暫存更改以及遠端分支狀態; - 符號導航器(Symbol navigator):專案中的可識別符號如類名、方法以及變數名都可以在這裡檢視; - 檔案查詢導航器(Find navigator):查詢專案中的某個檔案以及位置; - 問題導航器(Issue navigator):可以檢視專案在構建或執行時出現的問題或者警告; - 測試導航器(Test navigator):專案執行時可以檢視CPU、記憶體以及磁碟等的佔用情況,方便後續優化,若新增斷點還可以檢視堆疊呼叫資訊; - 斷點導航器(Breakpoint navigator):方便管理專案中加入的斷點,快速定位斷點位置; - 報告導航器(Report navigator):檢視專案在構建執行以及除錯時的日誌資訊;

2 程式碼靜態分析

  程式碼靜態分析通過掃描程式碼,查詢違反預程式設計規則的問題,如記憶體洩露和緩衝區溢位,可以有效提高程式碼質量,值得注意的是Xcode中的靜態程式碼分析適用物件只有C、C++、Objective-C,除此之外如程式碼追蹤和效能檢測的工作應結合instruments使用,後面會介紹instruments及其使用。接下來我們會介紹如何開啟程式碼靜態分析的功能以及如何使用它解決常見問題。

2.1 使用方式

一般快捷鍵為 Command + Shift + B , 也可以通過Xcode 頂部工具欄選擇Analyze。

執行之後便可以在問題導航區看到問題提示,雙擊後可以直接定位到程式碼處,可以看到右邊紅框的提示即為邏輯錯誤,這裡漏掉了一個父類方法的呼叫。值得注意的是因為是靜態分析,所以並不能檢測出所有錯誤,且存在誤報風險,比如這裡的左邊紅框提示controller4並未使用,其實最後在執行時狀態UI會將其從陣列中取出並渲染;

2.2 靜態程式碼分析可以解決的常見問題

  • 邏輯缺陷 可以看到這裡返回了一個未初始化的值,與此同時IDE也會提示有變數並未初始化。

  • 記憶體管理錯誤

    這裡檢查到返回了一個空指標,但是函式並不希望返回一個空值。這裡檢查函式編寫邏輯也存在錯誤,增加預設判斷保證返回值不為空即可。

    當程式中包含潛在的記憶體洩露的問題時,靜態程式碼分析也可以檢測,這裡CoreGraphics框架下的CGColor需要我們手動管理記憶體,使用 CGColorRelease 釋放即可。

  • 無用儲存邏輯\ 這裡主要是指永遠不會訪問的變數以及永不會執行的程式碼。

    這裡提示 Value stored to 'cellNum' is never read 說明程式碼可以優化,直接返回需要的數值,可以去掉cellNum這個臨時變數。

  • API濫用 這裡的問題主要是忽略了一些OC物件的使用規則,陣列中不允許新增空值,除此之外字典中也不允許設定key和value為空值。

  • Xcode13新增檢查特性\ 在Xcode13中靜態程式碼分析器升級,可以捕獲更多的邏輯錯誤如死迴圈、NSAssert副作用、無用的冗餘程式碼等。這裡我們以NSAssert副作用為例,編寫程式碼後使用 Command + Shift + B 開啟靜態程式碼分析,可以看到提示condition中的語句會在release版本下丟棄,所以不應該將變數修改的程式碼放入condition中執行,這裡將對number的修改程式碼移至NSAssert函式之外即可,不僅是Objective-C中的NSAssert函式,C和C++中的Assert函式也可以捕獲異常。

3 LLDB常用指令與斷點使用

  斷點一般可以分為普通斷點,條件斷點,符號斷點,異常斷點,watch斷點,執行緒斷點。在敘述各個斷點的使用功能之前先介紹除錯區域工具欄以及常用LLDB指令。

3.1 斷點工具欄

在此我們還是先熟悉一下斷點相關的工具區及其用途。 圖中各標籤對應含義如下: - 1——斷點開關(Deactivate breakpoint),當為藍色時斷點開啟,點選後藍色消失,斷點關閉; - 2——繼續執行(Continue program execution),點選後會跳轉至下一個斷點,若沒有則程式進入執行狀態; - 3——單步執行(Step over),單步執行程式,方便觀察每一步的執行狀況,當遇到子函式不會進入而是執行完進入下一條語句; - 4——跳入函式(Step into),進入子函式中繼續執行; - 5——跳出函式(Step out),結束子函式執行跳轉到上一級函式; - 6——層級檢視(Debug View Hierarchy),檢視程式當前頁面的UI層級檢視,定位檢視元件層級關係; - 7——記憶體結構圖(Debug Memory Graph),直觀檢查是否存在如記憶體洩漏的問題; - 8——偵錯程式外觀設定(Environment Overides),設定真機或模擬器的深淺色以及字型字號等外觀元素; - 9——模擬定位(Simulate Location),設定真機或模擬器的定位位置; - 10——斷點處例項變數資訊(Variables View); - 11——LLDB終端,執行相關指令,清屏快捷鍵為 Command + K ;

3.2 常用LLDB指令

  • help指令——檢視LLDB提供的指令及其作用

    當我們想檢視某個具體指令的用法時可以使用 help commandName,可以看到其提示的諸多搭配用法以及含義。

  • command指令\ command指令主要用來管理自定義的一些LLDB指令,常常結合script或者source使用,command script import filePath 匯入自定義的指令,而 command source 指令用於執行指定檔案中的LLDB指令。LLDB會在幾個特定位置預載入一些內容,而~/.lldbinit檔案屬於其中之一。若本地並無此檔案可以自行建立,然後輸入以下內容並儲存,其中 fblldb.py 為facebook開源的chisel提供的定製LLDB指令集合的入口檔案,詳細內容以及安裝方式點選這裡,其中也包含如何添加個人定製的指令。 command script import path/to/fblldb.py 然後開啟LLDB除錯視窗,輸入以下指令,如此便可以呼叫chisel提供的除錯指令。除此之外,command source 指令還可以匯入個人定製的.lldbinit檔案,從而避免使用高達(Gundam)動態生成的.lldbinit檔案,無法包含自定義配置項,而在.lldbinit檔案中新增 command script import 指令也可以算作自定義配置的一種。 command source ~/.lldbinit

  • p指令——列印基本資料型別
  • po(print object)指令——列印物件

    除此之外po指令還能和oc中的方法結合使用。

    當自定義一個類時,呼叫po指令。

    這時並沒有顯示我們需要的資訊,需要重寫KSEText類的debugDescription方法。

    再次執行po指令。

  • call指令——動態呼叫函式\ 執行指定函式,在不重新編譯的情況下更改檢視,除此之外,call指令同樣可以執行表示式

  • expr指令(expression)——執行指定的表示式\ 若執行下述操作出現報錯提示可以使用 expr videoController.tabBarItem.title = [NSString stringWithUTF8String:"短視訊"] 來解決(出錯原因)。

  • image指令——查詢異常地址\ 這裡我們模擬陣列越界的情況,接著使用image指令查找出錯位置(當然後面會介紹使用異常斷點直接定位),而 image list 可以檢視當前專案所有引入的庫,常用於檢視某個外掛是否注入自己的專案。 模擬程式碼如下。

    下面是出錯的提示資訊,可以看到前面的CoreFoundation和libobjc.A.dylib和我們關係不太大,可以直接從序號4開始查。

    執行 image lookup -a(image lookup --address),可以看到Summary部分提示了出錯位置為AppDelegate.m檔案中的53行18列。

  • bt指令——列印執行緒堆疊資訊 bt all 列印所有執行緒堆疊資訊

    當只需要部分堆疊資訊時,可以在 bt 指令後面新增具體列印的行數資訊。

3.3 斷點使用

  • 普通斷點\ 在程式碼中某一行點選最前面的數字就可以新增普通斷點,當程式執行至斷點處便暫停執行,注意斷點對應的程式語句是沒有執行的。從下圖中可以看到,程式目前暫停在了36行,且前面的斷點標籤即數字1所指的位置是亮藍色,當再次點選圖示會變暗,狀態變為disable;

    數字2指向的按鈕功能為跳轉至下一個斷點,當後續沒有斷點時,程式會進入執行狀態,如下所示,後面的按鈕也會進入禁用狀態。

    當我們新增多個斷點想要統一管理時,便可通過左上角的斷點導航器檢視,雙擊則跳轉至斷點處。普通斷點可以結合LLDB指令使用,排查程式碼邏輯是否符合預期。

    而點選左上角的除錯導航器圖示則可以檢視程式執行的記憶體CPU等資源的佔用情況,除此之外還可以檢視當前執行緒的函式呼叫棧;

    如下圖所示,從左邊的堆疊呼叫關係可以看到,main 函式間接呼叫了 KSECollectionViewController的方法 [collectionView:cellForItemAtIndexPath:],然後[collectionView:cellForItemAtIndexPath:] 方法呼叫 GTReuseableCell的 [initWithFrame:]方法。

  • 條件斷點\ 新增條件斷點,我們可以在原先普通斷點的基礎上進行編輯修改使其成為條件斷點。右鍵斷點選擇“Edit Breakpoint...”

    在Condition一欄新增我們設想的邏輯條件,然後執行程式,當符合斷點條件時,程式便會停留在斷點處。

    當然我們還可以在符合斷點條件時執行指定的動作,點選Add Action進入選擇介面。

    點選紅框框選按鈕,可以看到有六個選項,各自作用分別為: - AppleScript:執行指令碼檔案; - Capture GPU Workload:用於OpenGL ES除錯,捕獲斷點處GPU當前繪製幀; - Debugger Command:和控制檯中輸入LLDB除錯命令一致; - Log Message:輸出自定義資訊至控制檯; - Shell Command:接收命令檔案及相應引數列表,Shell Command是非同步執行的,只有勾選“Wait until done”才會等待Shell命令執行完再執行除錯; - Sound:斷點觸發時播放聲音;

    除此之外,當我們在迴圈中設定斷點後可以使用Ignore選項跳過前面N次,直接檢視需要的資訊。

    而下方的Options選項選中後斷點不會終止程式執行。

  • 符號斷點\ 對一個方法下斷點,當程式呼叫此方法時觸發斷點,這裡可以是OC方法或者C++函式,常用於除錯第三方庫,給相應函式下斷點,檢視程式當執行流程。這裡新增方法相比之前並不相同,這裡先點選左上方的斷點導航工具圖示,進入斷點檢視介面。

    點選左下方的”+“按鈕,然後選中Symbolic Breakpoint...進入符號斷點新增介面。

    在輸入符號時可以只輸入函式名,也可以按[類名 函式名]的方式輸入,還可以在前面加上類方法或者例項方法修飾符。

    - 異常斷點(全域性斷點)\ 用於快速定位由於程式丟擲異常而導致退出,如常見的陣列越界,新增方法同符號斷點,選中斷點導航器,點選左下角“+”號,選擇Exception Breakpoint...,隨後進入異常斷點設定介面。

    這裡我們主要配置兩個地方,Exception和Break,Exception可以選擇Objective-C、C++以及All,值得注意的是,當程式使用異常來組織框架邏輯,這時候選擇All會頻繁觸發異常,所以這種情況更適合選擇Objective-C;而Break主要選擇在丟擲異常還是捕獲異常的時候斷點。

    這裡還是以陣列訪問越界的例子,演示異常斷點如何定位問題位置。當我們新增異常斷點後執行程式得到如下圖所示結果,相比image指令,異常斷點會直接跳轉至錯誤程式碼位置並清晰指出異常觸發原因。

    - 執行緒斷點\ 執行緒斷點適用在除錯多執行緒程式碼的時候,一段程式碼可能會被多個執行緒同時執行,設定方法為,首先在程式碼處新增普通斷點,然後獲取輸入指令thread info 獲取執行緒id,然後在LLDB中輸入指令 breakpoint set -f filename -l line_number -t tid

    執行 breakpoint list 指令可以檢視當前包含的所有斷點,因為設定斷點是邏輯斷點,而一個邏輯斷點對應一個或多個位置斷點,當載入新的程式碼時也會同時更新位置斷點,邏輯斷點和位置斷點使用“.”分割。

    當想禁用或者刪除斷點時可以執行指令breakpoint disable/delete breakpoint_number

    - Watch斷點\ 常用於跟蹤某個變數發生的變化,當發生變化時觸發斷點。設定方法為,在變數第一次出現的位置新建普通斷點,然後在Variables View視窗選中需要監控的變數並右鍵,選擇Watch "_text",這時便可以在斷點導航器中檢視到新建的Watch斷點。

    當被監控變數發生變化時便會觸發斷點,並在LLDB終端顯示,幷包含新舊值對比。

    繼續執行,可以看到控制檯輸出後續變化的監測資訊。

    這時的資訊是十六進位制,若需要檢視其具體含義,則可以使用po指令。

    在實際開發中,可能需要使用逆向工程的方式來觀測某個變數的變化,這個時候我們可以使用LLDB的命令列來新增Watch 斷點,好處在於可以直接使用變數地址進行監測,指令格式為 watchpoint set expression address ,刪除Watch斷點可以使用 watchpoint delete <cmd-options> [<watchpt-id | watchpt-id-list]的可選引數為 -f (force)。

3.4 除錯例子

這裡我們嘗試執行程式,使用 Command + R 指令,但程式構建失敗,報錯如下,我們找到和我們密切相關的部分,這裡我們優先定位紅框標出的部分。

使用image lookup -a 0x00000001049707ae 指令查找出錯位置,資訊如下。

感覺對我們幫助不大,這裡main函式是主入口,也是專案初始化生成的部分。

我們嘗試使用全域性異常斷點獲得其他的異常資訊。這裡新建異常斷點(Exception Breakpoint),引數使用預設值。再次執行程式得到以下資訊,點選綠色斷點資訊將其展開,可以看到提示“UITableView dataSource returned a nil cell for row at index path:...",我們的TableView返回了一個空值導致了程式崩潰。這裡我們可以自己定位程式碼中哪裡有使用過TableView也可以直接使用靜態程式碼分析。

因為程式構建就崩潰,我們優先嚐試使用靜態程式碼分析檢查錯誤。這裡使用 Command + Shift + B 指令,得到如下提示,也幫我們定位到了程式碼問題所在,在呼叫[tableView: cellForRowAtIndexPath:]方法時返回了空值。所以我們需要修改程式碼邏輯,在最後補充預設返回值但不能為空,增加一個else語句。

程式碼修改如下所示,執行程式,成功執行,但是最後TableView並沒有顯示我們想要的結果。

這裡應該是存在內在邏輯錯誤,所以需要藉助斷點排查問題。這裡我們分別在 [tableView:numberOfRowsInsection:] 和 [tableView:cellForRowsAtIndexPath:] 方法的返回處新增普通斷點,因為這樣我們方便檢視最後的返回值,斷點所在行的程式碼是還未執行的。除此之外我們還在 [tableView:cellForRowsAtIndexPath:] 方法的if語句開頭處新增斷點,方便我們檢視indexPath變數的值。

我們先逐個排查返回值是否存在異常,這裡新增斷點後,程式便會停留在斷點處,我們再使用po指令輸出我們想檢視的值。這裡我們先檢視cellNum的值為2,並無異常,我們再檢視indexPath變數中的item屬性發現為空,則需要在程式中新增兜底邏輯,讓最後的cell返回非空值,這裡在第二張圖中也可以印證左邊variable視窗cell最後依然是空值。圖中為後續新增的else語句。

點選繼續按鈕,讓斷點往下執行,再次輸出indexPath的item屬性,並無異常。執行完斷點後便可以看到tableview顯示了一行結果。

\ 但是上面一行還是沒有資訊填充肯定是不符合預期的,繼續除錯。

這裡我們可以聚焦除錯導航欄,檢視程式呼叫的堆疊資訊,發現這裡它存在一個預生成邏輯,最初會生成一個全域性的cell方便後面複用(TableView中的cell需要註冊後使用,這樣可以在原來cell的基礎上修改少量顯示資訊便能展示新的cell,實現複用,極大提升效能)。

列印第一次返回的cell的資訊發現返回的text屬性都為空。

當繼續執行斷點,再次列印cell相關的text資訊,可以得到以下結果。

結合程式碼可以知道,當indexPath.item值為1時,這裡會使用懶載入生成cell然後賦值。

由此我們可以得到一個結論,第一次返回的是TableView建立的全域性cell但是text屬性值為空,這裡我們需要給第一次建立的全域性cell給一個合理的初值,然後執行程式碼,問題解決。

4 Log的使用

  雖然斷點功能強大,但這裡還是需要補充一樣不可或缺的工具——Log。有的時候除錯的時候bug無法復現,一旦關閉除錯,bug便會出現。這一般是出現在多執行緒中,除錯模式影響了多執行緒的執行。所以我們需要藉助Log去檢查程式執行順序是否符合預期。這裡我們需要藉助pch(Precompiled header)檔案設定我們的列印操作如何執行,至於pch檔案是什麼以及有何作用可以看這篇文章,Xcode6之後需要手動新增pch檔案,新增方法看這裡,完成第一步即可,這裡著重介紹如何在pch檔案中書寫Log規則以及在專案中引入pch檔案。

當我們在專案中生成了字尾為.pch的檔案後,雙擊開啟可以看到以下描述。

我們在#define和#endif中間新增需要的巨集,這裡我們新增以下內容。第11行的DEBUG標識可以幫助我們區分Debug和Release狀態,這樣在軟體釋出時日誌資訊便不會再列印。第12行中的KSELog為列印的方法名,可以自己定義。這裡增加了檔名以及行數的資訊列印,方便後續檢視Log日誌定位問題。

```

ifndef KSELog_pch

define KSELog_pch

ifdef DEBUG

#define KSELog(...) \ NSLog(@"%@第%d行:%@\n---------------------------",[[NSString stringWithFormat:@"%s",FILE] componentsSeparatedByString:@"/"][[[NSString stringWithFormat:@"%s",FILE] componentsSeparatedByString:@"/"].count-1], LINE, [NSString stringWithFormat:VA_ARGS]);

else

define KSELog(...)

endif

endif / KSELog_pch /

```

之後我們需要在專案中引入pch檔案。首先我們需要開啟專案的target找到Apple Clang - Language,這裡可以使用過濾器快速定位。

然後我們需要將 Precompile Prefix Header 屬性置為Yes,除此之外需要在Prefix Header部分新增pch檔案的絕對路徑,這裡可以藉助Finder和Terminal快速獲取檔案路徑,將Finder中的檔案拖入Terminal便可以得到列印的路徑資訊。這裡需要雙擊箭頭指向的部分,進入編輯模式,將複製的路徑貼上進去即可。

效果檢視。

5 Instruments

  Instruments是功能強大的效能檢測和程式碼追蹤工具,常用於記憶體洩露檢測,效能分析,支援多執行緒除錯,可以將錄製的圖形介面操作和Instruments儲存為模板,供以後訪問使用。因為Instruments提供的功能較多,無法一一列舉,這裡主要介紹Leaks模版的使用。首先本文會簡要說明Instruments提供了哪些主要功能,然後聚焦於Leaks模版的使用。開啟方式為,點選頂部工具欄的Product,然後選擇Profile即可。

5.1 主要功能(基於Xcode 13.4)

常用模板:

  • Allocations:用來檢查記憶體分配,跟蹤過程的匿名虛擬記憶體和堆的物件提供類名和可選保留/釋放歷史
  • Leaks:一般用來檢視記憶體使用情況,檢查洩漏的記憶體,並提供了所有活動的分配和洩漏模組的類物件分配統計資訊以及記憶體地址歷史記錄
  • Time Profiler:分析程式碼的執行時間,執行對系統的CPU上執行的程序低負載時間為基礎取樣
  • Zombies:檢查是否訪問了殭屍物件

  • Blank:建立一個空的模板,可以從Library庫中新增其他模板
  • Activity Monitor:顯示器處理的CPU、記憶體和網路使用情況統計
  • Animation Hitches:動畫監視,此模板通過時間分析來度量應用程式圖形效能以及程序的CPU使用情況
  • App Launch:啟動問題,可以用於檢視App的啟動過程,從而可以針對性的對啟動速度進行優化
  • Core Data:監測讀取、快取未命中、儲存等操作,能直觀顯示是否儲存次數遠超實際需要
  • CPU Counters:幫助開發者定位CPU佔用高的執行緒和函式,來優化App的CPU效能問題
  • CPU Profiler:週期性的CPU負載分析器,使用硬體效能監測中斷來提供可靠的效能監測,無論程式碼執行在高速還是節能的CPU上
  • File Activity:檔案活動,此模板監視檔案和目錄活動,包括檔案開啟/關閉呼叫、檔案許可權修改、目錄建立、檔案移動等
  • Game Performance:方便開發者瞭解對遊戲執行表現和幀率影響至關重要部分程式碼的執行情況
  • Logging:統一的日誌管理系統,方便將日誌和線索視覺化。引入歸檔日誌檔案時的預設模版
  • Metal System Trace:金屬系統跟蹤,Metal System Trace通過提供來自應用程式、驅動程式和GPU層的跟蹤資訊,介紹了iOS、tvOS和macOS Metal應用程式的效能
  • Network:分析應用程式如何使用TCP / IP和UDP / IP連線使用連線儀器。就是檢查手機網速的。(這個最好是真機)
  • SceneKit:概述應用程式對SceneKit的使用。確定進入每個幀的工作型別,例如動畫、物理、場景選擇和渲染
  • System Trace:系統跟蹤,作業系統中發生的事情的一個全面的觀點。瞭解如何跨cpu排程執行緒,瞭解系統呼叫和虛擬記憶體錯誤如何影響應用程式的效能

5.2 Leaks模版

如上所述,Leaks模板主要用來檢測記憶體分配情況,查探是否發生了記憶體洩漏,一般和Allocations結合使用。這裡以Xcode 13.4版本為例,演示Leaks模板的使用。首先我們在示例程式碼中增加一段會引發記憶體洩漏的程式碼,如下所示。我們簡單定義一個結構體,然後模擬申請記憶體但不釋放的情況,因為ARC只針對NSObject,所以這裡的記憶體空間是需要手動回收的。

我們按照先前提示步驟開啟Profile介面,選擇Leaks,然後進入分析介面。注意此時程式碼是沒有執行的,需要點選分析介面左上角的紅色同心圓,開始程式的檢查分析。

分析介面如下所示,上面一欄Allocations是分析程式碼的記憶體分配情況,下面一欄Leaks是檢測是否發生了記憶體洩漏,綠色標識指明暫未發現記憶體洩漏,紅色標識表明檢測到發生了記憶體洩漏。這裡我們以C語言中的結構體申請但不釋放為例,演示Leaks模板的使用。

示例程式碼如下,重寫KSEViewController的Init方法,新增記憶體申請程式碼。邏輯為在主介面點選跳轉到KSEViewController對應的介面,然後返回,因為結構體Book為自定義結構,需要手動釋放,若返回到主介面未釋放記憶體則會被檢測到記憶體洩漏。

注意使用Instruments模版需要先在Xcode中編譯執行,然後按步驟開啟模版檢測。這裡可以看到在Leaks一欄出現了紅色標識,我們點選右下方的Stack Trace中的堆疊記錄,跳轉到對應含有記憶體洩漏風險的程式碼處,修復Bug。

6 除錯補充

6.1 view hierarchy的使用

在進行UI介面開發時,常常需要觀察頁面層級關係以及位置關係,這時就可以使用Xcode中自帶的Debug View Hierarchy,開啟方法為執行專案程式後點擊下方的Debug View Hierarchy,等待程式載入完畢後,就可以看到。

  • 1——Adjust the spacing between the views:調整檢視間的間隙,一般是由2D檢視轉變為3D檢視;
  • 2——Show/Hide Clipped Content:展示或者隱藏當前介面沒有被展示的內容;
  • 3——Show/Hide Constraints:展示或者隱藏介面約束;
  • 4——Adjust View Mode:調整檢視模式,可選僅內容展示、僅線框展示以及內容和線框同時展示;
  • 5——Change canvas background color:改變畫布的背景顏色,深色模式和淺色模式,支援真機;
  • 6——Orient to 2D/3D:調整檢視為2D或者3D模式
  • 7——Adjust the visible range views:調整可見的檢視範圍;

6.2 真機截圖

實際開發中,有的時候需要給產品或者測試人員展示介面效果,這個時候就可以使用Xcode中的截圖功能,當我們選擇頂部導航欄的 Debug 選項,然後找到 View Debugging ,最後點選 Take Screenshot of xxx的iPhone ,這樣就能獲得存放在桌面位置的真機截圖。

總結

本文主要結合了個人的經驗和查閱的資料,希望能對iOS的開發者們有所幫助,在這裡找到需要的Debug技巧。如果內容有所不足,還請批評指正,有任何問題,也希望多多留言,共同探討進步!

hi, 我是快手電商的小毅

快手電商無線技術團隊正在招賢納士🎉🎉🎉! 我們是公司的核心業務線, 這裡雲集了各路高手, 也充滿了機會與挑戰. 伴隨著業務的高速發展, 團隊也在快速擴張. 歡迎各位高手加入我們, 一起創造世界級的電商產品~

熱招崗位: Android/iOS 高階開發, Android/iOS 專家, Java 架構師, 產品經理(電商背景), 測試開發... 大量 HC 等你來呦~

內部推薦請發簡歷至 >>>我們的郵箱: [email protected] <<<, 備註我的花名成功率更高哦~ 😘