OC基礎回顧(六)瞭解和使用Xcode

1.瞭解IDE窗口

(1)窗口布局一覽

窗口包括:工具欄,導航器面板,編輯器面板,調試器面板,檢查器面板和庫面板。
可以按住Command鍵+一個數字鍵(從1到7)或點擊導航器面板的頂端的圖標來切換導航器面板的視圖。



在窗口的右上角有一組工具欄按鈕




(2)更改公司名稱的方法

新建Objective-C源文件時,Xcode會自動幫你生成註釋文字。如下:
//
//  ViewController.h
//  LearnXcode
//
//  Created by SharonHu on 15/7/14.
//  Copyright (c) 2015年Sharon. All rights reserved.
//


Xcode在註釋塊中生成了文件名稱、項目名稱以及創建者和創建日期。
我們可以自己更改公司名稱。
方法是:在導航器面板選中項目,在檢查器面板的Project Document欄目下的Organization文本框中輸入你的公司名稱,在Class Prefix文本框中可以輸入文件的前綴。如下圖所示:



(3)一些使用技巧

A.過濾列表文件

使用導航器面板底部的搜索框可以過濾源列表文件,例如下圖搜索出了名稱中帶有guide的文件。你可以在任意的導航器視圖中使用這個搜索框。




B.窗口顯示文件:
雙擊導航器面板中的某一個文件,可以用獨立的全屏窗口顯示這個源文件,這在比較兩個不同文件時很有用。也可以用兩個不同的窗口顯示同一個文件,但是要注意有時候這兩個窗口的內容會出現不同步的情況,因此需要點擊其中某個窗口來使他們同步。

C.標籤顯示文件:
也可以用標籤的顯示方式(就像Safari一樣)。顯示標籤的方法:View →Show Tab Bar選項,如下圖:




2.Xcode偏好設置

通過“Command+逗號”快捷鍵或”Xcode|Preferences”菜單呼出偏好設置。

(1)主題及字體(Preferences->Fonts & Colors)

選中一種主題theme),例如“Midnight”,然後shift選擇Source Editor/Console中的所有項,點擊Fonts設置字體。Xcode默認字體爲menlo,可選Consolas、Monaco等其他等寬字體。

(2)文本編輯配置(Preferences->Text Editing)

Editing:

  • Show Line Numbers:在編輯面板中顯示行號。
  • Code folding ribbon:顯示摺疊ribbon。
  • Page guide at column:顯示一行最多支持80個字符的提示分割線。
Indentation:
  • Prefer indent using:Spaces(爲保持一致的視覺呈現和行末註釋對齊,建議使用空格)
  • Tab width:4 spaces(tab expand,1個tab=4個空格)
  • Indent width:4 spaces(自動縮進步長=4個空格)

(3)SCM(Preferences->Source Control)

Enable Source Control:啓用/禁用XCode自帶Source Control Manager(SCM)。

(4)SDK/Simulator(Preferences->Downloads)

Downloads->Components:可下載SDK和Simulator。

(5)構建輸出目錄(Preferences->Locations->Locations)

  • 當選擇爲Default時,Derived Data的目錄爲~/Library/Developer/Xcode/DerivedData。
  • 當選擇爲Relative時,Derived Data的目錄爲當前.xcodeproj所在的目錄。
  • 當選擇爲Custom時,Derived Data的目錄需自定義。
    不建議使用絕對路徑,因爲寫死之後,換環境或換平臺,又要重新修改路徑,建議使用相對路徑(Relative

3. 在Xcode的幫助下編寫代碼

(1)首行縮進(美觀排版)

選中文本後,按住Control鍵點擊(或直接右擊),在彈出來的上下文菜單中選擇Structure → Re-Indent選項,Xcode會將代碼重新排版。
快捷鍵Control + i 可以達到同樣的效果。




通過Structure菜單,或者按下Command+ 【 鍵和 Command + 】鍵可以將選定的代碼進行左移或者右移。

Xcode →Preferences → Text Editing → Indentation , 自定義Xcode內的代碼風格。

(2)代碼自動完成

編寫程序時,Xcode會爲所有內容生成索引,包括項目中的比變量名和方法名以及導入的框架。當輸入代碼時,Xcode會不斷地比較你輸入的代碼和它生成的符號索引,如果匹配,Xcode就會給出建議。下圖是我輸入N時出現的自動完成列表:

E:枚舉符號
f:表示函數
#:表示#define 指令
m:表示方法
C:表示類
等等

(3)批量編輯

   創建快照 :選擇File  → Create Snapshot 選項(或者 Command + Control + S 快捷鍵)(如下圖),Xcode會記住項目目前的狀態,然後就可以隨便編輯源文件而不用擔心把項目“玩壞了”。




     如果意識到自己犯了一個嚴重的錯誤,可以通過File → RestoreSnapshot選項,打開快照窗口,這樣就可以選擇一個快照恢復項目了。如下圖:


說明:快照文件存儲在~Library/Developer/Xcode/Snapshots/目錄中。


(4)查找替換功能

在導航器面板中選擇搜索選項,或者快捷鍵Command + Shift + F,就可以對整個項目中的所有文件進行內容搜索和替換。可以點擊Replace All對整個項目應用這個替換。


(5)重命名某一個符號的名稱

選中一個符號,如局部變量或者參數,然後點擊它,出現一個向下的箭頭:


點擊這個箭頭,出現一個菜單,選擇Edit all in Scope選項。


你會發現文件中所有使用了這個符號名稱的地方都出現了一個虛線框,這時,在任意一個虛線框裏修改符號名稱,其他虛線框裏的符號也會同時被修改。這個功能太棒了!只要單擊編輯面板中的其他地方,就能退出Edit all in Scope模式了。


注意,如果發現Edit all in Scope菜單被禁用,這是因爲這個功能與Xcode中的語法着色功能密切相關,如果你對語法着色功能改動過多或者關閉了它,Edit all in Scope功能也就停止工作。要解決這個問題,需要回到設置菜單,對語法着色功能進行調整,直到他能恢復工作。

(6)通過Xcode內置的重構工具修改類的名字
把光標放在類名上,右擊,出現一個菜單列表,選擇Refactor → Rename


在彈出的對話框中輸入替代的類名:


可以點擊Preview按鈕,查看將要修改的地方:


確定修改沒有問題後就點擊Save。如果是第一次在項目中重構代碼,Xcode會詢問你是否要啓用自動快照備份,選擇yes是一個明智的決定。
注意:重構並不能重命名註釋中的文字。可以用查找替換功能簡化這一操作。


4.代碼導航

在代碼的生命週期中瀏覽代碼的不同方法。

(1)emacs快捷鍵組合

指的是一些不用把手從鍵盤上拿開就能在文字中移動光標的快捷鍵。
emacs是一個很早就有的文本編輯器,它誕生在20世紀70年代,可以在現代的Mac操作系統上運行。

下面是這些按鍵及其功能:
Control-F :光標前(Forward)移效果(效果同右方向鍵
Control-B:光標後(Backward)退(效果同左方向鍵
Control-P:光標移動到上(Previous)一行(效果同上方向鍵
Control-N:光標移動到下(Next)一行(效果同下方向鍵
Control-A:光標移動到行首位置(效果同Command + 左方向鍵
Control-E:光標移動到行末位置(效果同Command + 右方向鍵
Control-T:交換(Transpose)光標兩邊的字符
Control-D:刪除(Delete)光標右邊的字符
Control-K:把當前光標以後的所有字符全部刪除(Kill),便於重寫行尾的代碼。
Control-L:將光標置於窗口的正中央。如果你找不到光標的位置或者想要移動窗口使光標快速移動到正中央,這個快捷鍵會非常好用。

(2)快速打開的竅門

竅門一:快速查找並打開一個文件
File → Open Quickly(或者快捷鍵Shift + Command + O





打開了一個對話框,在搜索框中搜索關鍵詞,就可以查找與這個關鍵詞有關的文件:




訣竅二:同時顯示頭文件和它對應的實現文件
View → Assistant → Show Assistant Editor(或者快捷鍵 Option + Command + 回車鍵)。默認情況下如果一個面板顯示的是頭文件,那麼另一個面板顯示的就一定是實現文件,不過可以根據自己的喜好更改這一設定。點擊工具欄的Counterparts菜單,就可以看到其他選項。





(3)代碼摺疊(code folding)

緊挨着源代碼左側有兩個空欄:分別是邊欄聚焦欄


注意聚焦欄的灰度,代碼嵌套的越深,它的灰度就越深。這中顏色編碼能夠使代碼的複雜程度一目瞭然。
在不同灰色區域懸停鼠標可以高亮顯示響應的代碼片段



(4)編輯面板上方的導航條

點擊菜單按鈕,可以看到快速打開最近訪問的歷史文件或執行其他高級的操作。
點擊前進後退按鈕,可以打開曾經編輯過的文件
功能菜單顯示當前光標所在的方法,點擊功能菜單可以看到文件中所有的符號。如下圖所示:


藍色高亮的地方,說明光標當前位於-tableView:heightForHeaderInSection:這個方法中。
按住Command鍵,並且點擊功能菜單,就可以將文件中的方法按照字母順序排列,如下圖:


可以向菜單中加入其他內容。
有兩種方法:一是使用#pragma mark whatever, 後面的whatever可以填寫任何的文字,它會出現在菜單中。
#pragma -(減號),會在菜單中插入分割線。Xcode也會在註釋裏查看那些諸如“MARK:”(與#pragma mark 的功能相同)、“TODO”、“FIXME”、
“ !!!:”和“ ??? :”之類符號開頭的文本,並將這些文本放入功能菜單中。最程序發佈之前,最好先看看這些標記。


5.獲取信息

(1)獲得幫助

檢查器面板頂端有兩個圖標
點擊第一個圖標,檢查器顯示的是當前文件的各種屬性。


點擊第二個圖標,檢查器中啓用快速幫助(Quick Help)功能。在代碼中點擊任意位置,快速幫助面板會更新。


(2)文檔管理程序

之間訪問蘋果公司的官方API文檔的方法:按住Option鍵並且雙擊某個符號,就跳轉到與該符號相關的文檔中。如果按住Option鍵並且雙擊NSString,將會打開文檔瀏覽器並搜索NSString,如圖示:



6.調試運行

(1)Console & Scheme

shift+command+Y:顯示控制檯(Show/Hide the debug area)

shift + command + K:清除控制檯(Clean)

option+command+R:編輯配置(Edit Scheme

(2)Build

Product -> Edit Schemeoption+command+R)->Info->Build Configuration:選擇生成版本(Debug or Release)

command + B:構建(Buid)

(3)Target

一個定義好構建過程的Target成爲一個Scheme,可在Scheme中定義Target的六種構建過程:Build/Run/Test/Profile/Analyze/Archive。

一個Target是指在一個Project中構建的一個產品,它包含了構建該產品的所有文件,以及如何構建該產品的配置。

Product -> Edit Schemeoption+command+R)->Manage Schemes可對Scheme的六種構建過程進行配置(可配置項包括Info、Arguments、Options)。

在Project Navigator中選中某個xcodeproj(例如QQ.xcodeproj),將進入Project Setting頁面,可點擊左側圖標show/hide project and targets list:




點擊targets項可分別設置各target的Build Settings;右擊可對target進行delete。



(4)Issue & Errors

編譯錯誤(error)和警告(warning)過多時,只顯示編譯錯誤


點擊底端的感嘆號,即可只顯示編譯錯誤,忽略編譯警告:




(5)Run

command + R:運行(Run),可能會先編譯。若按下control直接運行上次build的product(Run Without Building)。

command + .:停止運行(Stop)

(6)Breakpoint

command + \:當前行設置/取消斷點;通過鼠標點擊藍色斷點來啓用/禁用當前行斷點。

command + Y:全局激活或禁用所有的斷點,激活進入調試模式(此時斷點藍色可見)。

邊列(Gutter)中的斷點/警告可右鍵呼出Reveal in Breakpoint/Issue Navigator。

trick:編輯斷點(Edit Breakpoint):

Condition:設置斷點的觸發條件,例如“i==3”(注意不能有空格)表示當i等於3時該斷點纔會被觸發。

Ignore:設置斷點需要被忽略多少次纔會中斷,若設置成5則表示第6次遇到該斷點時才觸發。

Action:設置斷點觸發時的動作,可以爲Debugger Command、Log Message、Shell Command或Sound。

例如可設置以下Debugger Command:

(1)讀取std::string sig的內存buffer值:mem read sig.c_str() -c sig.size()

(2)打印NSData實例sig:po sig



(7)Debug

F6:下一步(Step Over),逐過程單步調試,不進入函數體。

(fn+)F7:進入(Step Into)函數體。可能與多媒體鍵有衝突,故需要fn輔助。

(fn+)F8:跳出(Step Out)函數體。可能與多媒體鍵有衝突,例如呼叫iTunes,故需要fn輔助。

control+command+Y:逐斷點(continue)繼續執行。

trick:移動指令指針Move the instruction pointer):


斷點調試運行時,可以將綠色指針箭頭(Line 47)移動到其他行(Line 49)或其他斷點(Line 51)實現跳轉執行。


(8)Watch

shift+command+M:Debug Workflow->View Memory

command+K:Debug Workflow->Clear Console

Debug Workflow->Show Disassembly When Debugging,可進行彙編指令級調試。

trick:修改變量內存值change memory value while debugging):

調試運行時,可以在底部的調試窗口(Debug Area,可通過Shift+Command+Y呼出)右鍵某個變量,除了可以進行View Memory/View Value As之外,還可以選擇Edit Value運行時編輯內存變量的值。

這種手動設置指定值,在調試某些難以復現的bug或進行邊界測試非常有用,可以避免在驗證某個問題時反覆改值重新編譯。


(9)lldb調試命令

  • n/next:step over;
  • s/step:step into;
  • finish:step out;
  • c/continue:goto next breakpoint;
  • expr/expression:Evaluate a C/ObjC/C++ expression(動態執行C/ObjC/C++表達式);
  • p/print/expr/expression:print as a C/C++ basic variable;
// 打印SYSTEM_VERSION(可能要加UIDevice*轉換)
(lldb)p [[[UIDevice currentDevice] systemVersion] doubleValue]
  • po/expr -O/expression -O:Print as an Objective-C object;
// 打印屏幕bounds(可能要加UIScreen*轉換)
(lldb)po NSStringFromCGRect([[UIScreen mainScreen] bounds]) 
// 打印狀態欄frame(可能要加UIApplication*轉換)
(lldb)po NSStringFromCGRect([UIApplication sharedApplication].statusBarFrame)
  • call:調用。其實上述p/po後接表達式(expression)也有調用的功能,一般只在不需要顯式輸出,或是無返回值時使用call,用於動態調試插入調用代碼。
  • 例如可以在viewDidLoad:裏面設置斷點,然後在程序中斷的時候輸入以下命令:
// 調用後,繼續運行程序,view的背景色將變成紅色
(lldb) call [self.view setBackgroundColor:[UIColor redColor]]
  • bt(backtrace),打印當前調用堆棧(crash堆棧),“bt all”可打印所有thread的堆棧(相當於command+6的Debug Session Navigation)。
  • image:可用於尋址,有多個組合命令,比較實用的一種用法是尋找棧地址對應的代碼(行)位置。
  • 例如某個UITableView總共有2個section,當其引用的currentSection.index≥2時將會引起[UITableView rectForHeaderInSection:]調用異常,可使用expr動態改值製造crash場景模擬調試。
  • 此時crash時的控制檯bt顯示異常出現在應用層代碼“0x00d055b8 - [FACategoryTableView FACategorySectionHeaderDidTouched:] + 744”處(其中0x00d055b8爲當前棧(代碼段)偏移量,744爲棧幀偏移量——PC指針相對函數入口的偏移)。
  • 那麼具體是FACategoryTableView.m文件哪一行代碼調用引起的異常呢?此時通過“image lookup --address”後接bt的call stack中的代碼段偏移地址(0x00d055b8)即可定位出異常調用的代碼行位置。
  • memory write:改寫指定地址的內存(Write to the memory of the process being debugged)。可help mem write查看幫助:

  • x/memory read:dump指定地址的內存(Read from the memory of the process being debugged),後接起止地址或-c指定count加起始地址。可help mem read查看幫助:

Syntax

memory read <cmd-options> <address-expression> [<address-expression>]

Command Options Usage:

size指定內存塊(block/item)的大小,默認爲1byte。

    --size <byte-size> ):The size in bytes to use when displaying with the selected format.

count指定內存塊(block/item)的個數,可配合起始地址使用。

    -c <count> ( --count <count> ):The number of total items to display.

format指定內容顯示格式,格式符同print:c-char,s-string,d-decimal,x-hex。

    -f <format> ( --format <format> ):Specify a format to be used for display.

Command Samples:

(a)起止地址

(lldb)mem read 0x10b88f0c 0x10b88f0c+9

0x10b88f0c: 39 38 37 36 35 34 33 32 31                       987654321

(b)起始地址+內存塊count

(lldb)mem read 0x10b88f0c -c 9

0x10b88f0c: 39 38 37 36 35 34 33 32 31                       987654321

(c)起始地址+內存塊size+內存塊count(dump hex format)

(lldb)memory read -s 1 -f x -c 9 0x10b88f0c

0x10b88f0c: 0x39 0x38 0x37 0x36 0x35 0x34 0x33 0x32

0x10b88f14: 0x31

(d)起始地址+內存塊size+內存塊count(dump char format)

(lldb)memory read -s 1 -f c -c 9 0x10b88f0c

0x10b88f0c: 987654321

(e)起始地址+內存塊size+內存塊count(dump string format)

(lldb)mem read 0x10b5cf2c -f s -c 1

0x10b88f0c: "987654321"

(f)起始地址+內存塊size+內存塊count(dump int format)

(lldb)memory read -s 4 -f x -c 3 0x10b88f0c

0x10b88f0c: 0x36373839 0x32333435 0x109f0031

Syntax: memory write <cmd-options> <address> <value> [<value> [...]]



(10)啓用NSZombieEnabled調試EXC_BAD_ACCESS

當你對已釋放的對象發送消息(90%的可能是對引用計數爲0的對象再release)或release那些autorelease對象時,就會出現報EXC_BAD_ACCESS這樣的錯誤。
默認設置下 Xcode不會給你定位具體是哪一行代碼不該去使用已釋放的對象,或者release用錯了。
Product -> Edit Schemeoption+command+R -> Diagnostics ,勾選“Objective-C”之後的“Enable Zombie Objects”。
設置NSZombieEnabled環境變量後,一個對象銷燬時會被轉化爲_NSZombie;設置NSZombieEnabled後,當你向一個已經釋放的對象發送消息,這個對象就不只是報EXC_BAD_ACCESS Crash,還會放出一個錯誤消息,然後以一種可預測的可以產生debug斷點的方式消失, 因此我們可以找到具體或者大概是哪個對象被錯誤的釋放或引用了。
注意NSZombieEnabled只能在調試的時候使用,千萬不要忘記在產品發佈的時候去掉,因爲NSZombieEnabled不會真正去釋放dealloc對象的內存,一直開啓後果自負!





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