最全最詳細的注釋使用說明
[TOC]
前言
- 好的代碼本身就是一種注釋
- 代碼的可讀性更重要
注釋的作用
代碼的意義,除了完成功能業務這一最基本的要求之外,最終還要讓別人能夠讀懂你的代碼,讓別人看得懂這段邏輯的意義,讓別人更快更準確的理解這個方法的使用規則,同時使代碼層級分明,方便快速瀏覽,以及生成使用文檔等等。總之就是方便自己與他人后期維護。尤其是多人維護同一個項目的時候,注釋的意義不言而喻,注釋到位,別人去維護你寫的代碼時,就不會那么頻繁的問你,甚至背后問候你了~~~
常用的注釋分類
個人理解,對于注釋的分類,從宏觀功能上劃分,可以分為 代碼注釋 和 特殊功能注釋。
代碼注釋又可以從位置特點上細分,可以分為單行注釋,行尾注釋(多用于屬性、枚舉值),多行注釋(方法,協議,類等)。
下面我將從剛剛說的幾個維度去介紹。
環境介紹
- demo日期:2019.1.1
- macOS 10.14.1
- Xcode 10.1
- 示例代碼語言:Objective-C
代碼注釋
需要寫代碼注釋的地方非常多,包括不限于以下場景:文件的注釋、類的注釋、一段代碼邏輯的說明;屬性、枚舉、方法、block等聲明的注釋
單行注釋
最常見的就是這下面這樣樣式:
示例代碼:
/* 這個方法的功能是做這個事情的,要注意呀~ */
+ (void)method {
// 這里邏輯是這樣的,要注意呀~
[self new];
}
/// 單行注釋10
@property (nonatomic, copy) NSString *str10;
//! 單行注釋11
@property (nonatomic, copy) NSString *str11;
/** 單行注釋12-可用于多行 */
@property (nonatomic, copy) NSString *str12;
/*! 單行注釋13-可用于多行 */
@property (nonatomic, copy) NSString *str13;
上面兩種注釋方法,都是最最常見的普通注釋的寫法,兩種寫法但凡是寫注釋的地方都能用上,能夠滿足注釋最基本的提示功能,沒有什么特別要說明的。不過有一個缺陷是不會有 [option + 單擊] 時Xcode的注釋提示,所以和下面的單行注釋分開說。
使用場景大多是代碼塊中,對于一些邏輯關鍵的的描述。另外,個人比較喜歡前后都加上一個空格的寫法。
后面四種寫法無論是否加空格,使用上都沒有區別,都會有Xcode補全時的提示,以及 [option + 單擊] 時的提示。
總之,單行注釋適合無入參邏輯簡單的 類、方法、block 等的注釋。
也可以用于屬性或枚舉的注釋,不過,屬性枚舉注釋個人認為更適合用行尾注釋。
行尾注釋
行尾最大的特點,就是在三個注釋符號加上一個<小于號緊密的湊在一起。
示例代碼:
@property (nonatomic, copy) NSString *str20; ///< 行尾注釋20
@property (nonatomic, copy) NSString *str21; //!< 行尾注釋21
@property (nonatomic, copy) NSString *str22; /**< 行尾注釋22 */
@property (nonatomic, copy) NSString *str23; /*!< 行尾注釋23 */
個人覺得行尾注釋使用場景最多在于屬性的聲明和枚舉值定義,這時候這么寫一行就展示的下,屏幕大的時候看代碼清晰明了。
有幾個注意點(對于屬性和枚舉):
- 所有上述寫法,無論是否帶空格,無論是在.h或.m中,Xcode代碼補全時會有提示
- 在.h中,四種寫法都能 [option + 單擊] 顯示方法注釋
- 在.m中,只有 [///<不帶空格] 這種注釋寫法點擊才會顯示注釋
也就是說,[///<不帶空格] 這種注釋寫法是最簡單有效的行尾注釋寫法。不過,我總覺得不帶空格總是不夠優雅~
行尾注釋不能適用于單行注釋,否則和最最普通的注釋無差別。
另外,如果屬性含義過于復雜,尤其是存在多種狀態時,可以使用多行注釋的寫法。
多行注釋
示例代碼:
手動寫的樣式:
/**
* 方法注釋test02
*/
- (void)test02 {}
/*!
* 方法注釋test03
*/
- (void)test03 {}
Xcode生成的樣式:
/**
這是一個多參數的方法
@param count 參數0,數量
@param str 參數1,字符串
@param objc 參數2,對象
@return 返回值,返回值bool情況說明
*/
- (BOOL)testC0WithCount:(NSUInteger)count str:(NSString *)str objc:(id)objc {
return YES;
}
效果如圖:
上面兩種沒有什么好說了,具體就是看個人喜好與團隊風格了。下面說一下各個關鍵字的使用。
參數list:
注釋中常用的標簽:
關鍵字 | 說明 |
---|---|
@brief | 使用它來寫一段你正在文檔化的method, PRoperty, class, file, struct, 或enum的短描述信息。 |
@discusstion | 用它來寫一段詳盡的描述。如果需要你可以添加換行。 |
@param | 通過它你可以描述一個 method 或 function的參數信息。你可以使用多個這種標簽。 |
@return | 用它來制定一個 method 或 function的返回值。 |
@note | 注意點,補充說明 |
@see | 用它來指明其他相關的 method 或 function。你可以使用多個這種標簽。 |
@sa | 同上 |
@code | 使用這個標簽,你可以在文檔當中嵌入代碼段。當在Help Inspector當中查看文檔時,代碼通過在一個特別的盒子中用一種不同的字體來展示。始終記住在寫的代碼結尾處使用@endcode標簽。 |
@remark | 在寫文檔時,用它來強調任何關于代碼的特殊之處。 |
/**
* 各種關鍵字的使用示例
@brief 使用它來寫一段你正在文檔化的method, PRoperty, class, file, struct, 或enum的短描述信息。
@discusstion 參數用它來寫一段詳盡的描述。如果需要你可以添加換行。
我換兩行試試
第三行呢?
@param str 參數
@return 返回值,返回值bool情況說明
@note 注意點,補充說明
@see - (BOOL)testC0WithCount:(NSUInteger)count str:(NSString *)str objc:(id)objc{}
@sa 同上
@code
使用這個標簽,你可以在文檔當中嵌入代碼段。當在Help Inspector當中查看文檔時,代碼通過在一個特別的盒子中用一種不同的字體來展示。始終記住在寫的代碼結尾處使用標簽
// 方法
- (void)testb0 {
NSLog(@"注釋標簽");
}
@endcode
@remark 在寫文檔時,用它來強調任何關于代碼的特殊之處。
* 其他注釋
*/
- (BOOL)testC1WithParam:(NSString *)str {
return NO;
}
效果如圖:
附加:
記錄文件常用標簽:
關鍵字 | 說明 |
---|---|
@file | 使用這個標簽來指出你正在記錄一個文件(header 文件或不是)。如果你將使用Doxygen來輸出文檔,那么你最好在這個標簽后面緊接著寫上文件名字。它是一個top level 標簽。 |
@header | 跟上面的類似,但是是在 HeaderDoc中使用。當你不使用 Doxygen時,不要使用上面的標簽。 |
@author | 用它來寫下這個文件的創建者信息 |
@copyright | 添加版權信息 |
@version | 用它來寫下這個文件的當前版本。如果在工程生命周期中版本信息有影響時這會很重要。 |
@class | 用它來指定一個class的注釋文檔塊的開頭。它是一個top level標簽,在它后面應該給出class名字 |
@interface | 同上 |
@protocol | 同上兩個一樣,只是針對protocols |
@superclass | 當前class的superclass |
@classdesign | 用這個標簽來指出你為當前class使用的任何特殊設計模式(例如,你可以提到這個class是不是單例模式或者類似其它的模式)。 |
@coclass | 與當前class合作的另外一個class的名字。 |
@helps | 當前class幫助的class的名字。 |
@helper | 幫助當前class的class名字。 |
特殊功能注釋
特殊功能注釋展示效果通常都是在類的方法list中,也就是 [ctrl + 6] 快捷鍵顯示的方法列表。
Pragma mark
這個通常用于一類方法的歸納
示例代碼:
#pragma mark - Life Cycle
- (void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark - Delegate
#pragma mark UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
return nil;
}
#pragma mark UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
#pragma mark - Event Response
#pragma mark - Getters UI
效果如圖:
可以看到,通過 pragma mark 使用,可以讓方法分門別類,快速定位。
使用的注意點:
- pragma mark 和 pragma mark - 都算是關鍵匹配對象,不可少打或改變大小寫,
- 對于pragma mark,mark后面只要不是字母,就都可以正常識別。
- 對于pragma mark - ,中劃線前后都一定有空格,在代碼列表中,會在其文字描述的上方顯示一個分割線
注釋標簽
標簽的功能類似于Pragma mark,會在類的方法列表中展示對應的提示文案和特定icon,支持的有以下幾種注釋標簽。
- MARK: 文本內容,等同于#pragma mark
- TODO: 文本內容,等待實現的功能
- FIXME: 文本內容,需要修正的功能
- !!!: 文本內容,需要改進的功能
- ???: 文本內容,有疑問的功能
代碼示例:
/**
* *** 打印一句話我要用好多代碼注釋標簽 ***
* MARK: 等同于#pragma mark
* TODO: 等待實現的功能
* FIXME: 需要修正的功能
* !!!: 需要改進的功能
* ???: 有疑問的功能
* 另外,可以加上特定前綴方便檢索,效果依舊不變
* ET_TODO: 等待實現的功能
*/
NSLog(@"注釋標簽");
效果如圖:
說明點:
- 五種提示都是關鍵字符串匹配,大小寫和冒號都不能錯
- 基于上面一點,可以自定義特定前綴,方便檢索(一堆TODO: !!!: 的項目還是很感人的)
這個可是說是本人最喜歡的功能了,尤其是在代碼中要特別強調說明一些事情時。
warming
這個沒有什么過多說的,其實在使用好各種標簽后,完全沒有必要使用warming去產生一個讓人煩惱的黃色標志。
示例代碼:
#warning 這里是代碼warming
#warning code warming
效果如圖:
但是需要注意的一點是,warning對于中文支持是存在問題的,我測試發現所有中文都不展示,且第一個單詞的首寫字母一定會被大寫展示。
attribute
__attribute__表示屬性,是Clang(GNU C)提供的一種源碼注釋,
方便開發者向編譯器表達訴求,一般以__attribute__(*)的方式出現在代碼中。
為了方便使用,一些常用屬性被定義成了宏,經常出現在系統頭文件中。
比如NS_CLASS_AVAILABLE_IOS(9_0) 就是 __attribute__(availability(9.0))
這個屬性的簡單寫法。
下面介紹一些可能會頻繁使用到的屬性
iOS-Foundation使用
AFNetworking使用
SDWebImage使用
對于中attribute函數屬性
- 函數屬性(Function Attribute)
- noreturn
- noinline
- always_inline
- pure
- const
- nothrow
- sentinel
- format
- format_arg
- no_instrument_function
- section
- constructor
- destructor
- used
- unused
- deprecated
- weak
- malloc
- alias
- warn_unused_result
- nonnull
- 類型屬性(Type Attributes)
- aligned
- packed
- transparent_union,
- unused,
- deprecated
- may_alias
- 變量屬性(Variable Attribute)
- aligned
- packed
- Clang特有的
- availability
- overloadable
高級應用-生成注解
ET_TODO:下期
注釋的使用
主要使用快捷鍵
- cmd + / 快速注釋選中行的代碼 (單行或者多行)
- command + Option + /,快速高級的邏輯注釋(常用于方法)
- option + 單擊 顯示注釋指示內容
- 使用多行注釋一段邏輯 /* */,多行注釋不可嵌套多行注釋
代碼片段
Xcode的代碼片段(Code Snippets)可以用來自定義代碼塊,方便快速開發
示例代碼:
@property (nonatomic,strong) <#Class#> *<#object#>; ///< <#note#>
關鍵寫法: <#這里是默認提示的文本#>
- 添加方式步驟1
步驟1圖中關鍵說明
關鍵字 | 含義 |
---|---|
Title | 為你設置的代碼短的標題 |
Summary | 方法片段摘要說明 |
Completion Shortcut | 為你設置的快捷代碼,當你在Xcode中輸入你設置的快捷代碼就會出現改代碼段 |
Completion Scopes | 為你需要設置的啟動作用域,如某些方法內就不能啟動快捷代碼段 |
- 添加方式步驟2
- 添加方式步驟3(后續修改查看)
生成文檔
headdoc http://developer.apple.com/opensource/tools/headerdoc.html
appledoc http://gentlebytes.com/appledoc/
docxygen
docxygen 感覺是這 3 個工具中支持語言最多的,可以配置的地方也比較多。我大概看了一下文檔,覺得還是比較復雜,而且默認生成的風格與蘋果的風格不一致。就去看后面 2 個工具的介紹了。另外,它雖然是開源軟件,但是沒有將源碼放到 github 上讓我感覺這個工具的開發活躍度是不是不夠。
- headerdoc
headerdoc 是 Xcode 自帶的文檔生成工具。在安裝完 Xcode 后,就可以用命令行:headdoc2html + 源文件名 來生成對應的文檔。我個人試用了一下,還是比較方便的,不過 headerdoc 的注釋生成規則比較特別,只生成以 /*! */ 的格式的注釋。還有一個缺點是每個類文件對應一個注釋文件,沒有匯總的文件,這點感覺有點不爽。
- appledoc
appledoc 是在 stackoverflow 上被大家推薦的一個注釋工具。有幾個原因造成我比較喜歡它:
它默認生成的文檔風格和蘋果的官方文檔是一致的,而 doxygen 需要另外配置。
appledoc 就是用 objective-c 生成的,必要的時候調試和改動也比較方便。
可以生成 docset,并且集成到 Xcode 中。這一點是很贊的,相當于在源碼中按住 option 再單擊就可以調出相應方法的幫助。
appledoc 源碼在 github 上,而 doxygen 在 svn 上。我個人比較偏激地認為比較活躍的開源項目都應該在 github 上。
相對于 headerdoc,它沒有特殊的注釋要求,可以用 /** */ 的格式,也可以兼容 /*! */ 的格式的注釋,并且生成的注釋有匯總頁面。
以下步驟主要參考該篇博客, https://blog.csdn.net/xborong/article/details/85057696 </p>
appledoc-官方博客
appledoc-ibireme博客
appledoc-唐巧博客
的博客中的過程都有點問題
appledoc version: 2.2.1 (build 1334)
工具安裝
git clone git://github.com/tomaz/appledoc.git
cd ./appledoc
sudo sh install-appledoc.sh
腳本編寫
#!/bin/bash
appledoc \
--output ./Doc \
-i *.m \
--project-name "IGUIKit" \
--project-company "Tencent" \
--no-create-docset \
--keep-undocumented-objects \
--keep-undocumented-members \
--no-warn-undocumented-object \
--no-warn-undocumented-member \
./IGUIKit
生成的文檔截圖樣式
結語
關于注釋,兩年前自己就做過一次較為全面的了解,算是形成了自己的一套注釋風格與規范,現在進一步再總結,過程中借鑒了Apple本身的注釋風格,一些開源框架的注釋風格,以及一些網上的博客,算是查缺補漏,也希望能夠幫助到各位。
注釋的寫法那么多,最關鍵的目的還是要寫,為了更好的閱讀代碼。至于你喜歡什么樣的注釋風格,自己喜歡的風格或者與團隊相近即可。
如果有什么建議或問題,歡迎溝通交流。
相關博客or文檔:
- 注釋規范
- 代碼結構風格
- iOS注解
- iOS快速代碼塊
- attribute說明
-
appledoc在Xcode10中的集成
appledoc官方、ibireme、唐巧 的博客中的過程都有點問題
- appledoc-官方博客
- appledoc-ibireme博客
- appledoc-唐巧博客