本文由CocoaChina譯者YueWang翻譯自AppCoda
原文:Documenting Your Objective-C and Swift Code in Xcode with HeaderDoc and Doxygen
在一個應用的整個開發過程中涉及到了無數的步驟。其中一些是應用的說明,圖片的創作,應用的實現,和實現過後的測試階段。寫代碼可能組成了這個過程的絕大部分,因為正是它給了應用生命,但是這樣還不夠,與它同等重要的還有代碼的注釋和文檔編寫。不管代碼寫的有多好,如果缺少了對應的好的注釋文檔,很有可能在將來帶來麻煩。不幸的是,許多開發者都忽視或忽略了代碼文檔的重要性,而這非常糟糕,因為好的程序不僅僅是好的代碼。它需要更多的東西。
談到編寫注釋文檔,顯然我不是說僅僅簡單的在實現文檔裡添加幾行注釋。肯定是更多的東西。但是首先,為什麼對代碼進行注釋這麼重要?好吧,這裡有兩個情景:不管你是單獨工作,或者你是團隊的一份子。讓我們來分別解釋一下。
如果你是一個正在開發的應用的唯一開發者,有理由相信寫注釋文檔會消耗時間,所以忽略不做會讓你更迅速完成目標。除此之外,很容易說服自己既然都是獨立開發者了沒有太大必要來做注釋文檔。但是相信我,這將會是在應用開發期間做的最壞的決定。假設你成功的開發完成了應用,無論是在app store上銷售或者賣給你的客戶,然後你把它保存起來。六個月後,你必須要通過添加幾個新功能來創建一個這個應用的新版本。當你重新打開這個工程然後查看已有的代碼,在你寫下第一行新代碼之前一段時間,你會意識到一個殘酷的真相:你幾乎不記得任何東西!你做過什麼,你怎麼做的,為什麼要這麼做,都會很難回想起來!你必須通過一個痛苦的方法來在腦袋裡重新喚起這個工程,這個方法就是從工程的最開始,一行行的“解密”你的實現代碼。僅僅是幾行注釋根本沒什麼幫助,最終直到你理解所有東西之前會用很長的時間且花掉許多精力。正在讀這些內容的很大一部分的你們都可能遇到過那種情況,而且我很肯定的給你說過去我也遇到過。這種情況真的是噩夢一樣,那時你經常想干脆從頭開始做一個工程算了。當然,這裡提到的場景可能僅僅會是一個...場景,只要我們花一點點時間來編寫合適的注釋文檔。
另一方面,如果你是團隊裡的一員來開發工程,那麼避開給代碼寫注釋文檔將會是災難性的。當你給其他開發者分享代碼時,你必須解釋你的觀點(在代碼裡),當時做了什麼,是怎樣做的,當然其他的開發者也被要求做同樣的事情。沒有一個情形是大項目的開發者們對後面開發者們開發的代碼都有全面的了解,因為若是這樣,將會浪費掉很多不必要的時間。因此,在這種情況下的編寫注釋代碼一方面就像是做交流,另一方面也是幫助團隊裡的其它開發者了解你的代碼的含義。畢竟,每個程序員編寫代碼的風格都跟其他人不一樣,所以表達清楚你的代碼功能是件必須做的任務。
希望我把觀點表達清楚了,現在讓我繼續說說對於所有編程語言和所有平台都適用的合適的注釋文檔。不管你是對iOS,web或者桌面系統編寫應用:重點就是你在編寫代碼時就寫文檔,這樣對你(和對其他人)做代碼修訂時會更簡單以及不會花費太多精力。
正如你了解的,在這個教程裡我將會重點突出代碼注釋文檔當中最重要的方面。我將會對Objective-C 和 Swift做講解,因為這兩個語言都有許多開發者利用來寫應用,當然我也打算向你展示這兩個語言的相似和不同之處。更進一步,我會展示怎樣為你的應用創建完整的,web-based文檔,但是恐怕我必須說這仍然只是僅僅針對 Objective-C的一個選項。
作為一名使用Xcode ID的iOS開發者,你可能曾經想過對於兩種語言的注釋文檔選項應該是相同的。事實並不是這樣,同Objective-C 比Swift支持很少的注釋文檔選項,至少在我寫這個文章的時候是這樣。但是,它們都給你了充足的“補給”以便你可以寫出優秀的注釋文檔。我們會從Objective-C開始,因為它有很多不止是滿足需要的東西要講解,然後我們將會講解Swift代碼注釋文檔來結束這個教程。現在沒有必要講述細節的東西,因為我們將會在接下來的部分中看到。
在開始之前,讓我提示最後的兩件事情。第一,我不是試圖讓你偏執的寫文檔,而是說服你編寫合適的注釋將會提高你的編程生涯。第二,編寫代碼注釋文檔是你必須接受的習慣,而絕對不是浪費時間。
用Objective-C創建一個demo app
我們從創建一個使用Objective-C的新工程開始,這工程也是我們將會用來對接下來要看到的東西做測試的。如果你還沒做,打開Xcode然後創建一個新的工程。因為我們不會做一個真的demo應用,選中Single View Application 就可以了。
在下一步中,命名工程為DocDemoObjC,在Language下拉菜單中確保選中Objective-C 選項。
通過在硬盤上選擇一個保存工程的目錄地址來結束這個指南。
文檔化細節
正如你知道的,在Objective-C 和 Swift中寫一條注釋的最簡單辦法是用兩條斜槓,如下圖展示這樣:
// This is a comment.
你可以(且必須)像上面那樣來放置你的注釋,以便分清每個部分。但是,當談到代碼注釋文檔,我肯定不是指的上面的注釋。如果整個教程都專注於此肯定毫無意義。注釋文檔意味著以結構化的方法使用特殊的關鍵字,也叫標簽來寫注釋,使用特殊的符號來標示注釋區域,因此編譯器可以完美的理解這個過程。只有一些簡單的規則需要遵守。上面操作的所有結果就是你的注釋文檔可以在三個不同的地方展示:
除此之外,合適的代碼注釋讓你可以使用眾多的工具來為你的應用創建完整的HTML文檔,例如the HeaderDoc 和 Doxygen。它們兩個稍後會提到,而且你會看到我剛才所說的是怎樣實現的。
記住上面所說的,是時候更近一步了。當使用Objective-C寫代碼時有三種可能的方法來標示一個注釋文檔區域:
在這個教程實例中我們將會用第二種方法來寫我們的注釋文檔。我選擇它出於兩個原因:第一,它是唯一一個能被HeaderDoc識別的格式,而且如果注釋塊不是以它開頭,幫助頁也不會被生成。第二,盡管Doxygen更傾向於第一種格式,它也能識別第二種。因此,第二種格式將會在兩種方法下都適用。第三種格式通常在注釋一行時用到,例如屬性值時,因此、,我們還是堅持用第二種格式。
現在,當寫注釋文檔時,你可以使用特定的關鍵值(或標簽)。標簽被分為兩個大類:第一個是 top level 標簽,它可以用來指定哪種類型的代碼被注釋了,例如類,結構體,文件,等等。注意top level標簽不是必須使用,但是肯定會幫助導出工具(例如 HeaderDoc 和 Doxygen)創建出更好的結果。第二個是second level標簽,它指定了每個注釋文檔塊的細節。這個類型的標簽正是你需要的,因為每一個都定義了另外的注釋文檔部分。
下面我給出了最重要的second level標簽,但是注意了這並不是全部。我們稍後會看到一些 top level標簽。我這裡列出來的是最常用到的:
你可以在 這裡 (HeaderDoc User Guide)找到包含所有支持的標簽的列表。
注意@符號是每個標簽的前綴。同樣,你也可以在文本中使用特殊字符switches,這樣就可以改變它的類型和格式。例如,Text 以會讓 Text單詞成為黑體,同時Text也會讓 Text 單詞的類型為italic. 有趣的是你也可以把部分文本以代碼形式展現(不是代碼段),如果寫下@cText,當幫助文檔在Xcode上展現時,它會導致展示一個不同的字體格式。
除開上面說的,你也可以替換@符號為反斜槓(/)。那樣的話標簽就會像這樣被展示: /brief, /param, /return,等等。注意反斜槓最常在Doxyten 文檔系統裡面被使用,而@符號常在HeaderDoc裡面被使用。在這裡我們會在所有地方使用@,因為它在兩個系統中都通用。
Objective-C代碼文檔化
讓我們看看以上我提到的內容是怎樣使用的。打開ViewController.m文件,在類的私有部分中添加下面的屬性:
@interface ViewController () @property (nonatomic, strong) NSString *myName; @end
然後如下面所示添加注釋文檔:
/*! @brief This property knows my name. */ @property (nonatomic, strong) NSString *myName;
然後到viewDidLoad方法中,開始輸入這個屬性。你將看到在代碼填充彈出框裡我們剛剛寫下的注釋就在那裡!
而且不僅這樣。當在鍵盤上按住Option 鍵,點擊myName屬性就會讓幫助窗口彈出:
更多的,如果在Utilities面板打開 Help Inspector,你會在那裡也找到相同的文檔。
注意在上面的注釋當中@brief 標簽可以被去掉而不會導致任何問題。意味著下面的這條注釋也是有效的:
/*! This property knows my name. */ @property (nonatomic, strong) NSString *myName;
同樣的,下面的也一樣:
/** This property knows my name. */ @property (nonatomic, strong) NSString *myName;
而且下面的這條也一樣:
/// This property knows my name. */ @property (nonatomic, strong) NSString *myName;
讓我們來看看第一個怎樣展示文檔方法的簡單示例。此時你必須了解如果你的目標是創建一個HTML文檔,那麼只是公有方法(在頭文件裡的)的文檔是可見的。無論你在類的私有部分中寫的任何文檔在Xcode幫助文檔裡都是可見的,但是任何實現部分都沒有被導出到注釋文檔裡。所以,記住這些,現在讓我們在ViewController.h 文件裡定義一個公有方法:
@interface ViewController : UIViewController -(float)toCelcius:(float)fromFahrenheit; @end
很顯然,這個方法將會把華氏度轉換為攝氏度。現在我們來添加注釋文檔:
/*! @brief It converts temperature degrees from Fahrenheit to Celsius scale. @discussion This method accepts a float value representing the temperature in Fahrenheit scale and it converts it to the Celsius scale. To use it, simply call @c[self toCelsius: 50]; @param fromFahrenheit The input value representing the degrees in the Fahrenheit scale. @return float The degrees in the Celsius scale. */ -(float)toCelcius:(float)fromFahrenheit;
注意在上面我們使用HTML開關來讓所有包含的文字分別是粗體和斜體。同樣注意我們是怎樣使用@c開關來標識內嵌代碼
為了在Xcode幫助當中查看這個注釋文檔是怎樣展示的,先打開 ViewController.m 文件然後定義這個方法如下:
-(float)toCelcius:(float)fromFahrenheit{ return (fromFahrenheit - 32) / 1.8; }
然後把光標放到方法名上,在Quick Help Inspector裡查看:
可以看到Xcode把文檔裡的每個部分都格式化的展示出來。在help 彈出窗口裡也一樣(option鍵+點擊方法名):
如果在viewDidLoad 方法中調用這個函數,那麼就可以在函數自動填充窗口裡看到簡介描述:
很棒,是不是?可以想象你的代碼那樣文檔化後會變得多有幫助且能自我解釋清楚代碼意義,特別是當你同其他團隊人員一起工作時。
為了讓這個例子更加有趣,我們添加另一個公有方法正好可以做相反的事情:把攝氏度轉換為華氏度。打開ViewController.h文件,然後添加下面的方法聲明,以及它的文檔注釋:
*! @brief It converts temperature degrees from Celsius to Fahrenheit scale. @param fromCelcius The celsius degrees value. @return float The degrees in the Fahrenheit scale. @code float f = [self toCelsius:80]; @endcode @remark This is a super-easy method. */ -(float)toFahrenheit:(float)fromCelcius;
在上面段落裡我們添加了兩個新的標簽:一對 @code – @endcode標簽和@remark 標簽。你將會馬上看到它們是怎樣展示的。
我們到 ViewController.m文件裡去實現這個方法:
@interface ViewController () @property (nonatomic, strong) NSString *myName; @end
0
現在我們看看Help彈出框如下:
非常漂亮!現在你自己的文檔跟Xcode默認文檔比起來毫不遜色。
在進入下一部分前,打開ViewController.h文件,然後添加下面的屬性聲明(當然也包括注釋):
@interface ViewController () @property (nonatomic, strong) NSString *myName; @end
1
同它一起,導入AppDelegate類:
@interface ViewController () @property (nonatomic, strong) NSString *myName; @end
2
添加上面屬性到類裡面的原因就是稍後可以讓我們看到屬性值和我們已經創建好的方法是怎樣用文檔工具(HeaderDoc 和 Doxygen)被導出的。
文件、類、結構以及枚舉
在前面部分我們浏覽了寫屬性或方法時需要遵守的記錄文檔規則。我故意從屬性和方法開始介紹編寫文檔,因為你的大部分開發時間都是消耗在那裡。現在我們已經看到了最主要的部分,現在繼續看看怎樣對 files, classes, structs 和 enums 添加注釋。
讓我們從files開始,怎樣在Objective-C中寫下能提供信息的文檔。當同其他人分享編程工作時,或者當你以開放源代碼組件形式分發代碼時,那麼添加file documentation就是必須的,因為這是最佳的地方來向你的開發伙伴或者使用你代碼的人提供明確的信息。通常,你將要更關注header 文件(.h)以及在它裡面的描述信息,因為這些會保留在將被導出的最終文檔裡(並不在Xcode裡);但是,這並不代表你不需要在implementation文件中添加描述信息。不要忘記當在Xcode中打開工程時,所有的東西都在那兒,不僅僅是header 文件,因此保證你不會留下沒被記錄文檔的部分。除此之外,實現部分不會在導出文檔中看到,但是所有文件的描述信息始終都是可見的。
讓我介紹一些當你在記錄一個文件時會用到的新標簽:
當然你還可以使用更多的標簽,但是這些都是最常使用的一部分。我建議你通覽HeaderDoc 或 the Doxygen文檔,這樣就可以發現一些額外的你想使用的關鍵字。
現在我們來看對ViewController.h 頭文件添加注釋。找到文件的開頭,就在import 命令之前。在那裡添加下面的幾行:
@interface ViewController () @property (nonatomic, strong) NSString *myName; @end
3
你可以把Your_Name 替換成你自己的名字或者公司的名字。同樣的,使用 brief標簽而不是省略它是很好的習慣,因為它會讓文檔系統(在HeaderDoc 和 Doxygen中稍後將會看到)在輸出的HTML網頁上展示你在這兒添加的簡短描述。我再提醒一次,在Doxygen裡你可以使用反斜槓來代替“@”。同樣的,在這裡你將不會看到剛才說的文檔長什麼樣,但是我們將會在後續輸出HTML文件時展示。
以上的都很棒,但是實事卻是在大多數情況下,你創建的新文件裡由Xcode自動添加的提供信息的默認注釋都非常好而且夠用了。當你在團隊裡同其他人一起協作,並且每個成員必須描述清楚他負責的那些文件的細節信息時,或者當你打算使用 HeaderDoc 或 Doxygen來輸出一個工程的完整文檔時,又或者當你是獨立開發者但是工程擁有數量眾多的文件時,你可能想創建一個文件描述塊。不管怎樣,由你自己決定你的文檔系統需要完善到哪個level。
讓我們來看看怎樣對class或者protocol寫注釋文檔。再一次的,我只給出最常用的標簽。自己查看說明文檔了解更多標簽信息。
實際上,可能除了superclass你幾乎很少用到上面的標簽。可用標簽的列表很長,只是我覺得在這裡列出更多沒太大意義。必須指出的是從superclass開始以及下面的所有標簽,都不能被 Doxygen,識別,只能被HeaderDoc識別。同樣的,在Xcode裡的Quick Help和Help Popup彈出框裡展示的是各個標簽旁邊的值,而不會展示標簽本身。因此,用不用他們取決於你是否使用文檔系統以及使用哪一個。
@interface ViewController () @property (nonatomic, strong) NSString *myName; @end
4
現在,如果把光標移動到ViewController 類的名字時,或者按住option鍵然後點擊它,就可以在Xcode幫助窗口中展示了上面的描述。
可以看到標簽都沒有展示出來,但是在這種情況下並沒任何影響。
很棒的是這樣能使你在聲明這個類的對象時可以看到類的簡介。眼見為實,打開ViewController.m文件然後定位到viewDidLoad方法。在那裡,聲明一個本地ViewController對象。你將會在代碼補充窗口裡看到類的簡介。
按照上面的方法也可以對protocol添加注釋。在ViewController.h 文件開頭添加下面的幾行:
@interface ViewController () @property (nonatomic, strong) NSString *myName; @end
5
Option鍵+點擊protocol的名字就會看到注釋在Help 彈出框裡展示出來。
可以看到在上面,我們也聲明了一個delegate 方法。可能此刻你覺得那毫無意義,但是我故意把它放在這裡是作為示例demo;當我們使用HeaderDoc和Doxygen來導出文檔時就會在導出的頁面看到它了。
現在我們討論了files,classes 和protocols 希望你有了一個大概的了解,現在看看一些特殊示例:怎樣對structs 和 enumerations進行注釋。它們的共同點是在兩個當中都使用 @typedef top level 標簽,以此來標示注釋塊的開始(再次提醒使用top level 完全自願)。
特別是對於Doxygen系統,不使用@typedef標簽,你應該對structs使用@struct 標簽,對enums使用@enum標簽。
讓我們看以下的代碼。把它添加到ViewController.h 文件的interface之前:
@interface ViewController () @property (nonatomic, strong) NSString *myName; @end
6
現在把下面的注釋添加在它前面:
@interface ViewController () @property (nonatomic, strong) NSString *myName; @end
7
可以看到,出現了一個名叫@field的新標簽。這個標簽的目的是對struct裡面的每一個變量進行描述。再次,我必須強調HeaderDoc和Doxygen的不同之處。在HeaderDoc裡,這個標簽是可接受且有效的。但是,在Doxygen裡卻不是這樣。在這個案例裡我們做的僅僅是分開對每一個變量進行注釋。這樣做會使當我們在implementation文件裡使用它們時能展示出每個的注釋。我們來看看吧(注意標簽和變量上方的注釋有著不同的值,所以在後面會更輕松的區別出來):
@interface ViewController () @property (nonatomic, strong) NSString *myName; @end
8
如果現在到 ViewController.m 文件中定義一個這個struct的變量,無論輸入以上任何變量的一個都會在彈出窗口裡看到它的描述。
Enumerations也是同樣的,所以我把它作為練習留給你自己去創建一個enum類型然後進行注釋。非常簡單,是不是?當enum創建好後,到viewDidLoad方法裡去查看它的注釋會不會在Xcode的幫助選項裡展示出來。
查看錯誤
在先前的例子裡可以看到,在@param 標簽旁必須寫出變量名字,之後才是描述信息。當然,誤輸入一個變量名,特別是當它有些復雜時,以及創建的文檔包含錯誤都是很有可能的。但是,有個方法可以避免這種情況發生,我猜你可能並不知道Xcode可以在這時成為你的可靠助手。
盡管Xcode在文檔開始寫時就處理了,它也可以幫助你避免誤輸入任何變量名。只要開啟一個配置就能讓它做到這點。讓我們來看看我到底想表達的是什麼:
在 Project Navigator裡,點擊工程,找到Build Settings標簽,如下圖所示:
這樣做後,在搜索框裡輸入comments關鍵字然後等待下方給出的結果。其中一個結果就是名為Documentation Comments的配置,通常它的默認值是NO。你做的僅僅是把它的值設為YES,一切就緒。
現在,我們來看上面的配置是怎麼樣影響我們為代碼寫注釋的。打開ViewController.m 文件,然後到私有類中,在那裡我們將聲明一個私有方法。如下:
@interface ViewController () @property (nonatomic, strong) NSString *myName; @end
9
正如我們將要實現這個方法,它會返回所選擇的城市天氣值,單位就是先前提到的(華氏度或攝氏度)。現在,我們在它之前添加下面的注釋:
/*! @brief This property knows my name. */ @property (nonatomic, strong) NSString *myName;
0
當你把上面的注釋copy-paste到Xcode裡,一個警告就會在第一個變量被注釋時彈出,告訴我們變量名targetcityName在方法聲明裡找不到。猜猜怎樣?這是對的!我沒有輸入正確的變量名(targetCityName),而是輸入了錯誤的變量名(targetcityName)因為沒有大寫“city”的第一個字母。這是在大型工程擁有許多注釋時,我們可能會忽視的地方,但是幸好Xcode給了我們“另一雙眼”來幫助。
現在,如果你點擊警告欄左邊的三角icon,就會看到Xcode自動推薦了正確的變量名,只要點擊它就能修復。或者,自己修復它。
有了上面的這些,再也不需要擔心在寫文檔時誤輸入任何變量名了。
Producing Documentation With HeaderDoc(使用HeaderDoc生成文檔)
現在關於代碼注釋我們已經涵蓋了主要內容,現在進入另一個部分,讓我們看看怎樣創建包含往工程裡添加的注釋的HTML文件。在這個部分,我們將使用HeaderDoc,一個與寫入文件裡的文檔配合很棒的好工具。我推薦你訪問 這個網站 來了解更多信息。我們將使用HeaderDoc來輸出工程的所有注釋部分到HTML頁面裡。小工程這樣做可能沒太大意義,但是對於大型工程或你將為其他人提供自己的SDK時,一個對應的文檔會很有必要。HeaderDoc工具實際上是一個 command-line工具。它提供詳細的不同的分支來配置導出步驟,你可以在上面我提供的鏈接裡找到。這裡,我們將使用一個分支,那就是很有用的可以指定輸出目錄(保存被導出文檔的目錄)的分支。
我們來看怎麼做。首先,為即將被生成的文檔創建一個目錄。為了便於訪問,我在桌面建一個目錄,當然你也可以選擇任何你喜歡的目錄,只要你更新稍後會看到的path路徑。我在桌面上創建了一個DocDemo目錄,並在此添加了兩個子目錄:一個是HeaderDoc,一個是Doxygen。每個工具生成的文檔會讓在各自對應的文件夾中。
接下來,你必須打開Terminal,可以點擊LaunchPad > Other group > Terminal,來打開或者在Spotlight下輸入 terminal來打開。
現在,用terminal去定位到你的工程所在的目錄,使用下面幾個簡單步驟就可以達到目的:
然後點擊回車鍵,為了確保你在正確的目錄下可以使用pwd 指令(始終在terminal中)
在這裡我們要使用的HeaderDo指令叫做headerdoc2html,指令格式如下:
/*! @brief This property knows my name. */ @property (nonatomic, strong) NSString *myName;
1
OutputDirectory目錄是我們先前創建的目錄,而input目錄是工程文件存在的目錄。
現在,讓我們實際使用它。在terminal窗口,寫下或者復制粘貼下面的指令:
/*! @brief This property knows my name. */ @property (nonatomic, strong) NSString *myName;
2
注意:在-o後面有一個空格符號。
接下來,到Finder中找到將會存儲導出文檔的目錄。按照上面描述的步驟,拖拉目錄到terminal。之後,輸入input目錄地址且在後面加一個/符號。全部指令將會看起來像下面這樣:
/*! @brief This property knows my name. */ @property (nonatomic, strong) NSString *myName;
3
你將會看到很多東西展示出來,當前不需要特別留意。當它完成後,標記和復制下來output目錄地址,在terminal中輸入下面的指令:
/*! @brief This property knows my name. */ @property (nonatomic, strong) NSString *myName;
4
然後粘貼復制的路徑。按下回車鍵然後讓它運行。這個指令會創建一個內容頁的表格,這樣所有的注釋文件,類和方法都會展示在一個地方。
好了。現在定位到Finder,然後在浏覽器中打開masterTOC.html文件。下面是你將會看到的東西:
如果你點擊ViewController鏈接,下面是你將會被引導進入的頁面:
在這裡你會看到文件的描述信息,class,protocol和 struct以及指向它們的鏈接和簡短描述。在相同頁面上也會展示struct的詳細信息。
注意有一部分含有重復的值,那是因為我們又使用了@field標簽又在每一個struct變量的上方使用。如果你想,也可以重回到Xcode然後刪除掉其中的任何一個。接下來,在terminal中重新運行HeaderDoc指令然後回到這裡。
如果你點擊一個class鏈接,會跳轉到一個新的頁面,這裡你可以看到它的描述信息,在header文件中聲明的兩個methods和一個property。
現在,你已經看到了結果了,隨便浏覽文檔中的任何部分然後看看所有東西都是怎樣展現的。HeaderDoc的用處遠遠不止這些,但是這卻是在大多數情況下你需要的東西。
使用Doxygen生成文檔
現在讓我們拋開HeaderDoc然後來看看且使用一個廣泛流傳的注釋系統,叫做Doxygen。在查看它的細節之前,我想說Doxygen並不是一開始就是為了在Objective-C中生成注釋文檔而設計的。但是,它卻在針對C 和C++語言時可以完美的完成工作,你將會親眼目睹,它其實支持很多的語言。除開這些,它還包含非常多的注釋標簽,如果你決定了使用Doxygen工具來生成注釋文檔,那麼你可以使用任何標簽來擁有更棒的兼容性。
Doxygen是一個第三方應用想要使用它之前必須下載。對所有的操作系統它都要對應版本,所以當你並不是只為iOS開發時也都可以使用。此刻,我將給你三條很重要的鏈接:
在下載前,讓我提醒你可以在Doxygen的網站上找到比我先前提到的內容多得多的東西。實際上,正如下面的截圖所示,在左側有一個菜單面板,你可以使用它來找到的Doxygen各個部分的內容和數不盡的細節以及how-tos.
現在,訪問我剛才在上面給你的鏈接地址,然後滑到頁面的下方直到找到一個名叫A binary distribution for Mac OS X 10.5 and later的區域。點擊 ftp或http鏈接來初始化包下載過程。依據你的網絡速度,下載過程可能會需要幾秒鐘來完成,文件大小大概為55Mb。
下載完成後,打開包。然後找到Doxygen應用然後把它拖到你的Applications目錄下。
如果你不想把它添加到Applications目錄下也沒問題。可以把它拖到任何你想放的位置。比較,Doxygen是一個完全self-contained的應用,無論你把它放在哪裡,移除它只需要刪除它的APP文件。
假設現在你已經把它復制到了目錄下,點擊Lauchpad來輕松找到它。點擊它運行。
注意:如果得到一個提示信息說一個應用程序不能被打開是因為它來自沒有被認證的開發者,按照下面的步驟來跳過它:在Finder裡,打開Applications目錄。定位到Doxygen應用,然後按下Ctrl鍵+點擊它。在菜單中選擇Open 選項,然後在新的視圖框中點擊Open 按鈕。
現在把Doxygen應用放一邊,回到Xcode。我們將會在兩個標簽中做些改變,這樣所有東西都會被識別。確保打開ViewController.h文件,然後在描述塊裡替換@header top level標簽為@file標簽。還有,注釋中的struct塊也需要一些改變, @typedef 標簽都必須被@struct標簽替代。當這一切都做好後,又一次離開Xcode。
如果以前用過Doxygen,你肯定知道應該怎麼做。但是,這裡我假設你是第一次使用這個應用,所以讓我向你展示一些最重要的步驟。
下面是Doxygen第一次運行時的初始窗口:
在我告訴你正確的需要使用的設置信息前,有必要說明Doxygen提供兩個使用模式:Wizard模式由一個簡單且通用的方法組成,以及Expert模式,在這裡很多的配置信息都可以被指定這樣你可以定制化每一個輸出文檔的細節部分。
我不會把重點放在Expert模式上,因為要應用的配置條件高度依賴於每位開發者的個人需求。意味著我們將專注於Wizard模式,但是在此之前,我想還是有必要快速了解一下Expert模式。在主視圖區域裡點擊 Expert按鈕,馬上就會在主面板上看到給了你很多的配置信息。你可以上下滑動查看所有的配置,但是遠不止於此。在左邊,有一個小面板標題為Topics,點擊其他的topic就可以獲取它自己的配置。如果有時間,浏覽它們所有。你將會找到想在你的應用當中使用的有用的選項。
現在,我們把焦點放在Wizard模式。確保點擊到了正確的按鈕,這樣就可以跟上我將要描述的內容。首先,在視圖頂部我們必須指定Doxygen 從哪裡運行。點擊Select按鈕,然後在電腦裡選擇Application目錄,或者任何其他你把Doxygen應用拷貝進去的那個目錄。
接下來,我們來指定工程名字。在Project Name輸入框裡,輸入 DocDemo in Objective-C值(或者任何你想用的值)。如果你願意,也可以把下面的輸入框值都填上。在那之下,我們必須指定指向工程的路徑。再一次,使用Select按鈕且定位到工程的根目錄中。選中Scan recursively會很不錯,因為Doxygen就也可以掃描所有子目錄了。
最後,指定存儲生成的文檔的地方。如果你還記得的話,我們已經為此在桌面的 DocDemo 目錄下新建了子目錄Doxygen 。因此,點擊Destination Directory旁邊的Select按鈕,然後選中它。
接下來,在左邊的Topics列表裡,選擇Mode選項。在新的配置裡,選中All Entities 選項:
接下來,還是在Topics列表裡,選擇Output選項。在這裡你可以找到很多的導出選項。自由選擇任何你想要的output種類。在這個例子裡,我屏蔽了 LaTeX選項,只讓HTML有效。
最後,在Diagrams選項裡你可以保留默認設置。
現在是時候輸出文檔了。請確認在繼續之前一定要把先前的配置信息全部設置好。設置好了?很好,我們繼續吧。點擊Run按鈕(在Wizard和Expert 按鈕旁邊),然後現在在主視圖區域你可以看到一個名叫Run doxygen的新按鈕。點擊它讓應用幫你啟動創建HTML文件。在白色區域你將會看到一些output信息,如果事情出差錯了,你也會在這裡看到。
不管怎樣,只要它完成了,打開Finder然後定位到輸出目錄去查看導出文件。你會看到有一系列的文件被創建了,而你需要找到的就是 index.html文件。雙擊在浏覽器中打開它。其實如果你不是那麼在意非要看到導出的文件,可以簡單在Doxygen視圖裡點擊Show HTML output 。
這是在打開index頁面時看到的第一個屏幕。
它只是包含了我們先前設置的工程名,創建時間,和在頂部的許多鏈接。使用這些鏈接去浏覽一下相應內容。例如,如果點擊Classes鏈接,你就會得到一個包含了工程中的所有classes的列表。有趣的部分是在每個class旁邊都展示了它的簡短描述信息(僅僅是那些我們寫了的)。
下面是當你點擊 ViewController class時會看到的內容:
可以看到,工程中的方法和一個公有屬性的詳細文檔可以在這裡找到。另外一個有趣的地方是在Files菜單下面,在這裡所有的被分析的文件都被列舉出來,選中ViewController.h文件。在哪裡你可以找到文件的描述信息,以及我們聲明的所有東西:calss, protocol, 和struct。
使用More…鏈接來查看上面的所有內容的詳細信息。還有一個鏈接名字為“Go to the source code of this file.”如果點擊它,將會展現ViewController.h頭文件裡的代碼。注意不管在頭文件裡的任何public的內容,都可以在這裡展示出來。但是不要指望可以看到任何實現代碼。那些是“專屬於你”的。
好了,此刻我相信你已經對所有以上內容有了大概理解。定位到輸出的HTML頁面,回到Xcode中修改注釋文檔信息,然後重新導出所有內容。還有,不要猶豫去設置高級配置信息然後查看將會發生什麼。大體上,盡量多的體驗更多內容,然後更加熟悉Doxygen。無論是小工程還是大工程,它都是一個很棒的工具。
用Swift創建一個Demo App
讓我們再次翻開新的篇章,說說關於用Swift寫的代碼的文檔記錄。為了讓事情盡可能的清晰,我們創建一個新的工程,這次使用Swift。
因此,在Xcode中建一個之前,在第一步中指明應用的模板為 Single View Application。接下來,命名工程為DocDemoSwift,確保選中的語言是Swift。接著,選一個路徑來保存工程,讓Xcode創建好工程。
Swift代碼文檔化
用Swfit的代碼注釋文檔跟用Objective-C的比,沒那麼強大,我把為什麼這樣的討論放在最後。不幸的是,HeaderDoc和Doxygen都不支持Swift(至少現在是這樣,不能說將來會怎麼發展),現在的文檔格式是基於reStructuredText,它是一個開源工程並且可以在這裡找到更多信息。
這個教程裡先前看到的所有標簽,只有兩個可以在這個示例裡使用:param和return, 通常使用的是(注意這個在末尾的“s”)。還有,@或者反斜槓 / 都不支持。取而代之的是,這兩個標簽都被包含在了冒號裡,例如:param:。在這之後,變量名必須要寫,隨後寫上描述信息。
brief和discussion標簽沒有被使用,但是相關的地方可以如標簽意義描述那樣添加文檔,意味著在文檔最開頭的簡短文字會被當做簡介,而隨後的更大塊的文字內容會被認為是描述信息。
這裡的新的有趣的事情就是在描述部分,你可以添加有序的和無序的列表,連同描述信息一起。例如,添加一個有序列表你只需要寫下:
/*! @brief This property knows my name. */ @property (nonatomic, strong) NSString *myName;
5
對於無序列表,你可以使用星號(*),或者破折號(-)標志。例如:
/*! @brief This property knows my name. */ @property (nonatomic, strong) NSString *myName;
6
和:
/*! @brief This property knows my name. */ @property (nonatomic, strong) NSString *myName;
7
注意:如果你對Markdown 語法很熟悉,那麼你已經了解了上面的內容。
為了在討論區域添加fields,你只需要寫下field名字並且被冒號包圍,然後寫下描述信息:
/*! @brief This property knows my name. */ @property (nonatomic, strong) NSString *myName;
8
以上所有,包括那兩個標簽(param和returns)對於寫出恰當的文檔已經足夠。盡管不像在 Objective-C 裡有那麼多的選擇,我相信前面的所有內容已經足夠,因此我不會再展開。
我們到Xcode中來看看上面所說的示例。打開ViewController.swift文件,然後在裡面定義下面的方法(同 Objective-C 例子差不多):
/*! @brief This property knows my name. */ @property (nonatomic, strong) NSString *myName;
9
記住前面所說的對Swift寫的代碼的注釋文檔的描述,下面是我們怎樣把在Objective-C版本中的相同的注釋寫下的方法:
/*! This property knows my name. */ @property (nonatomic, strong) NSString *myName;
0
注意:在這裡我們使用的 /** – */ 標記。在Help彈出框裡查看,結果如下:
同樣,如果在viewDidLoad方法裡鍵入方法名字,簡短的描述信息會出現在代碼填充框裡:
現在,我們創建一個不做任何事情的超級簡單的新方法:
/*! This property knows my name. */ @property (nonatomic, strong) NSString *myName;
1
我們將會為這個方法的文檔創建列表和fields。你將會看到的只是一個示例,所以不要深究注釋裡的邏輯關系。
/*! This property knows my name. */ @property (nonatomic, strong) NSString *myName;
2
按住Option鍵然後點擊方法名,下面就是將會在Help彈出框裡展示的信息:
上面所有幾乎是你需要的所有記錄Swift寫的代碼的文檔。但是,在閱讀了reStructuredText手冊之後,一定要嘗試更多的選項(或者其中一些...它非常廣泛)。
總結
在這個教程裡我們已經看到了關於代碼注釋的很多方面的內容。我們介紹了 Objective-C和Swift,且都對每一個的最重要的規則都過了一遍。你會發現,在Objective-C 裡你可以使用更多的選項,但是,這些工具在針對Swift時也很好用。我今天展示的並不是所有。有很多其它的內容待你發現和利用,我的目的是向你介紹最常用的記錄文檔方法。在這裡你所看到的,是10個情況中9個你都會遇到的。還有,不要忘記了我們介紹的兩個有趣的工具,HeaderDoc和Doxygen。它們都可以輸出很棒的文檔,它們將會成為你友好的“朋友”。最後,我想再次突出強調注釋你的代碼是非常重要的工作。你可能經常會懷疑這點,但是相信我,在這點上花費的每一秒都是值得的。通過寫下合適的注釋文檔來幫助你自己和其他人,直指核心,解釋你的代碼中你所做的所有事情。如果你還不習慣這樣做的話,最好從現在開始,即便你已經不再是個年輕的開發者。回見!