- Cocoa代碼風(fēng)格指南之命名規(guī)范(一)
- Cocoa代碼風(fēng)格指南之排版規(guī)范(二)
- Cocoa代碼風(fēng)格指南之注釋規(guī)范(三)
- Cocoa代碼風(fēng)格指南之使用規(guī)范(四)
本文基于 Google 和 Apple 的代碼風(fēng)格指南中關(guān)于命名規(guī)范部分的總結(jié)捣炬。Apple 的指南基本都是命名規(guī)范赢笨,而 Google 的指南則的比較豐富蛉加。命名悼院、風(fēng)格、使用都有涉及缆蝉,但講的都是比較核心的規(guī)范掏呼。
注:本文只針對 Objective-C井佑。如果是 Swift ,你還需要再看下官方文檔的建議守呜。
- [Apple] :Apple 明確給出建議
- [Google] :Google 明確給出建議
- [General] :通用做法(主觀)
通用規(guī)則
- 通過命名可清晰的看出方法及其參數(shù)的作用型酥。避免歧義。并在此基礎(chǔ)上盡量做到簡短查乒。 [Google] [Apple] [General]
insertObject:atIndex: // 正確
insert:at: // 錯誤
- 即便命名很長也不要使用簡寫弥喉。除了本文最后那些歷史悠久的簡寫。 [Google] [Apple] [General]
destinationSelection // 正確
destSel // 錯誤
- 盡可能使用與 Cocoa 編程接口的命名保持統(tǒng)一玛迄。在不同類中實(shí)現(xiàn)相同功能的方法應(yīng)該具有相同的名稱由境。 [Apple] [General]
- (int)tag // 在 UIView, UIControl 中都具有相同的功能
- (void)setStringValue:(NSString *) // 在許多 Cocoa classes 中都具有相同的功能
所有方法/常量/變量/屬性都應(yīng)使用"小駝峰"命名法。除了本文最后那些廣為人知的大寫字母縮略詞蓖议。 [Google] [Apple] [General]
所有類/類別/協(xié)議使用“大駝峰”命名法虏杰。 [Google] [Apple] [General]
類
類名應(yīng)包含一個明確描述該類(或類的對象)是什么或做什么的名詞讥蟆。 [Apple] [General]
在為類添加實(shí)例變量是要注意:
- 避免創(chuàng)建 public 實(shí)例變量。 [Google] [Apple] [General]
- 使用 @private嘹屯,@protected 顯式限定實(shí)例變量的訪問權(quán)限攻询。 [Google] [Apple]
- 確保實(shí)例變量名簡明扼要地描述了它所代表的屬性。 [Google] [Apple] [General]
協(xié)議 [Apple] [General]
- 大多數(shù)協(xié)議僅組合一組相關(guān)的方法州弟,而不關(guān)聯(lián)任何類钧栖,這種協(xié)議的命名應(yīng)該使用動名詞(ing),以不與類名混淆婆翔。
NSLocking // 正確
NSLock // 錯誤
- 有些協(xié)議組合一些彼此無關(guān)的方法(這樣做是避免創(chuàng)建多個獨(dú)立的小協(xié)議)拯杠。這樣的協(xié)議傾向于與某個類關(guān)聯(lián)在一起,該類是協(xié)議的主要體現(xiàn)者啃奴。在這種情形潭陪,我們約定協(xié)議的名稱與該類同名。NSObject 協(xié)議就是這樣一個例子最蕾。這個協(xié)議組合一組彼此無關(guān)的方法依溯,有用于查詢對象在其類層次中位置的方法,有使之能調(diào)用特殊方法的方法以及用于增減引用計(jì)數(shù)的方法瘟则。由于 NSObject 是這些方法的主要體現(xiàn)者黎炉,所以 Apple 用類的名稱命名這個協(xié)議。
方法
- 參數(shù)前面的單詞要能描述該參數(shù)醋拧。而且方法名應(yīng)盡量讀起來就像句子慷嗜,所以應(yīng)該選擇與方法名連在一起讀起來通順的參數(shù)名。 [Google] [Apple] [General]
- (id)viewWithTag:(int)aTag; // 正確
- (id)taggedView:(int)aTag; // 錯誤
- 表示對象行為的方法丹壕,名稱以動詞開頭庆械。 [Apple] [General]
- (void)invokeWithTarget:(id)target:
- (void)selectTabViewItem:(NSTableViewItem *)tableViewItem
方法名稱中不要出現(xiàn) do 或 does,因?yàn)檫@些助動詞沒什么實(shí)際意義菌赖。也不要在動詞前使用副詞或形容詞修飾缭乘。 [Apple] [General]
如果方法返回方法接收者的某個屬性,直接用屬性名稱命名琉用。不要使用 get忿峻。 [Apple] [General]
- (CGSize)cellSize; // 正確
- (CGSize)getCellSize; // 錯誤
- 只有在方法需要間接返回多個值的情況下,才使用 get辕羽。 [Apple] [General]
- (void)getLineDash:(float *)pattern count:(int *)count phase:(float *)phase; UIBezierPath
- 細(xì)化基類中的已有方法:創(chuàng)建一個新方法逛尚,其名稱是在被細(xì)化方法名稱后面追加參數(shù)關(guān)鍵詞。 [Apple] [General]
- (instancetype)initWithFrame:(NSRect)frameRect; // UIView
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style; // UITableView, UIView 的子類
- 不要使用 and 來連接用屬性作參數(shù)關(guān)鍵字刁愿。 [Apple] [General]
- (int)runModalForDirectory:(NSString *)path file:(NSString *)name types:(NSArray *)fileTypes;
- (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes;
- 如果方法描述兩種獨(dú)立的行為绰寞,使用 and 來串接它們。 [Apple] [General]
- (BOOL) openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag; NSWorkspace
不要在方法的參數(shù)名中使用 pointer 或 ptr,讓參數(shù)的類型來說明它是指針滤钱。 [Apple] [General]
避免使用 one觉壶, two,...件缸,作為參數(shù)名铜靶。 [Apple] [General]
按照 Cocoa 慣例,以下關(guān)鍵字與參數(shù)應(yīng)聯(lián)合使用: [Apple] [General]
...action:(SEL)aSelector
...alignment:(int)mode
...atIndex:(int)index
...content:(NSRect)aRect
...doubleValue:(double)aDouble
...floatValue:(float)aFloat
...font:(NSFont *)fontObj
...frame:(NSRect)frameRect
...intValue:(int)anInt
...keyEquivalent:(NSString *)charCode
...length:(int)numBytes
...point:(NSPoint)aPoint
...stringValue:(NSString *)aString
...tag:(int)anInt
...target:(id)anObject
...title:(NSString *)aString
Delegate & DataSource [Apple] [General]
- 委托方法是那些在特定事件發(fā)生時可被對象調(diào)用他炊,并聲明在對象的委托類中的方法争剿。它們有獨(dú)特的命名約定,這些命名約定同樣也適用于對象的數(shù)據(jù)源方法痊末。
1.名稱以標(biāo)示發(fā)送消息的對象的類名開頭蚕苇,省略類名的前綴并小寫類第一個字符。
- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row;
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
2.冒號緊跟在類名之后(隨后的那個參數(shù)表示委派的對象)凿叠。該規(guī)則不適用于只有一個 sender 參數(shù)的方法涩笤。
- (BOOL)applicationOpenUntitledFile:(NSApplication *)sender;
3.上面的那條規(guī)則也不適用于響應(yīng)通知的方法。在這種情況下盒件,方法的唯一參數(shù)表示通知對象蹬碧。
- (void)windowDidChangeScreen:(NSNotification *)notification;
4.用于通知委托對象操作即將發(fā)生或已經(jīng)發(fā)生的方法名中要使用 did 或 will。
- (void)browserDidScroll:(NSBrowser *)sender;
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window;
5.用于詢問委托對象可否執(zhí)行某操作的方法名中可使用 did 或 will炒刁,但最好使用 should恩沽。
- (BOOL)windowShouldClose:(id)sender;
C形式的函數(shù) [Apple] [General]
- 函數(shù)命名與方法命名相似,但有幾點(diǎn)不同:
- 它們有前綴切心,其前綴與你使用的類和常量的前綴相同。
- 大寫前綴后緊跟的第一個單詞首字符片吊。
- 大多數(shù)函數(shù)名稱以動詞開頭绽昏,這個動詞描述該函數(shù)的行為。
NSHighlightRect
NSDeallocateObject
- 查詢屬性的函數(shù)有更多的規(guī)則要遵循:
- 查詢第一個參數(shù)的屬性的函數(shù)俏脊,省略動詞全谤。
unsigned int NSEventMaskFromType(NSEventType type)
float NSHeight(NSRect rect)
- 返回值為引用的方法订晌,使用 get颓帝。
const char *NSGetSizeAndAlignment(const char *typePtr, unsigned int *sizep, unsigned int *alignp)
- 返回布爾值的函數(shù),名稱使用判斷動詞 is/does 開頭酌伊。
BOOL NSDecimalIsNotANumber(const NSDecimal *decimal)
存取方法 [Apple] [General]
存取方法是指用來獲取和設(shè)置類屬性值的方法漫萄,屬性的不同類型卷员,對應(yīng)著不同的存取方法規(guī)范。
如果屬性是用名詞描述的腾务,則命名格式為:
- (NSString *)title;
- (void)setTitle:(NSString *)title;
- 如果屬性是用形容詞描述的毕骡,則命名格式為:
- (BOOL)isEditable;
- (void)setEditable:(BOOL)editable;
- 如果屬性是用動詞描述的,則命名格式為:(動詞要用現(xiàn)在時時態(tài))
- (BOOL)showsAlpha;
- (void)setShowsAlpha:(BOOL)showsAlpha;
- 不要使用動詞的過去分詞形式作形容詞使用。
- (void)setAcceptsGlyphInfo:(BOOL)flag; // 正確
- (BOOL)acceptsGlyphInfo; // 正確
- (void)setGlyphInfoAccepted:(BOOL)flag; // 錯誤
- (BOOL)glyphInfoAccepted; // 錯誤
- 可以使用情態(tài)動詞(can, should, will 等)來提高清晰性未巫,但不要使用 do 或 does窿撬。
- (void)setCanHide:(BOOL)flag; // 正確
- (BOOL)canHide; // 正確
- (void)setShouldCloseDocument:(BOOL)flag; // 正確
- (void)shouldCloseDocument; // 正確
- (void)setDoseAcceptGlyphInfo:(BOOL)flag; // 錯誤
- (BOOL)doseAcceptGlyphInfo; // 錯誤
常量
常量命名規(guī)則根據(jù)常量創(chuàng)建的方式不同而大為不同。
枚舉常量
1.使用枚舉來定義一組相關(guān)的整數(shù)常量叙凡。 [Apple] [General]
2.枚舉常量與其 typedef 命名遵守函數(shù)命名規(guī)則劈伴。如:來自 NSMatrix.h 中的例子:(本例中的 typedef tag(_NSMatrixMode)不是必須的) [Apple] [General]
typedef enum _NSMatrixMode {
NSRadioModeMatrix = 0,
NSHighlightModeMatrix = 1;
NSListModeMatrix = 2,
NSTrackModeMatrix = 3
} NSMatrixMode;
3.位掩碼常量可以使用不具名枚舉。如: [Apple] [General]
enum {
NSBorderlessWindowMask = 0,
NSTitledWindowMask = 1 << 0,
NSClosableWindowMask = 1 << 1,
NSMiniaturizableWindowMask = 1 << 2,
NSResizableWindowMask = 1 << 3
};
- 使用 typedef NS_ENUM/NS_OPTIONS 來聲明枚舉握爷。 [General]
C++11 標(biāo)準(zhǔn)擴(kuò)充了枚舉的特性跛璧,可以指明用何種“底層數(shù)據(jù)類型”來保存枚舉類型的變量。這樣做的好處是可以向前聲明枚舉變量饼拍。Foundation 框架中定義了一些輔助宏來指定用于保存枚舉值的底層數(shù)據(jù)類型赡模。這些宏具備向后兼容能力,如果目標(biāo)平臺的編譯器支持新的標(biāo)準(zhǔn)师抄,就使用新語法漓柑,否則改用舊式語法。所以建議這樣來使用叨吮。
typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {
UIViewAnimationCurveEaseInOut, // slow at beginning and end
UIViewAnimationCurveEaseIn, // slow at beginning
UIViewAnimationCurveEaseOut, // slow at end
UIViewAnimationCurveLinear
};
- const 常量 [Apple] [General]
- 使用 const 來修飾浮點(diǎn)常量或彼此沒有關(guān)聯(lián)的整數(shù)常量辆布。
- 枚舉常量命名規(guī)則與函數(shù)命名規(guī)則相同。const 常量命名范例:
const float NSLightGray;
- 其他常量 [Apple] [General]
- 通常不使用 #define 來創(chuàng)建常量茶鉴。如上面所述锋玲,整數(shù)常量請使用枚舉,浮點(diǎn)數(shù)常量請使用 const涵叮。
- 使用大寫字母來定義預(yù)處理編譯宏惭蹂。如:#ifdef DEBUG。
- 編譯器定義的宏名首尾都有雙下劃線割粮。如:__MACH__盾碗。
- 為 notification 名及 dictionary key 定義字符串常量,從而能夠利用編譯器的拼寫檢查舀瓢,減少書寫錯誤廷雅。Cocoa 框架提供了很多這樣的范例:
APPKIT_EXTERN NSString *NSPrintCopies;
實(shí)際的字符串值在實(shí)現(xiàn)文件中賦予。(注意:APPKIT_EXTERN 宏等價(jià)于 Objective-C 中 extern)
數(shù)據(jù)集合 [Apple] [General]
- 管理對象(集合中的對象被稱之為元素)的集合類京髓,約定要具備如下形式的方法:
- (void)addLayoutManager:(NSLayoutManager *)adObj;
- (void)removeLayoutManager:(NSLayoutManager *)anObj;
- (NSArray *)layoutManagers;
- 集合方法命名有如下一些限制和約定:
- 如果集合中的元素?zé)o序航缀,返回 NSSet,而不是 NSArray堰怨。
- 如果將元素插入指定位置的功能很重要芥玉,則需具備如下方法:
- (void)insertElement:(elementType)anObj atIndex:(int)index;
- (void)removeElementAtIndex:(int)index;
- 集合方法的實(shí)現(xiàn)要考慮如下細(xì)節(jié):
1.以上集合類方法通常負(fù)責(zé)管理元素的所有者關(guān)系,在 add 或 insert 的實(shí)現(xiàn)代碼里會 retain 元素备图,在 remove 的實(shí)現(xiàn)代碼中會 release 元素飞傀。
2.當(dāng)被插入的對象需要持有指向集合對象的指針時皇型,通常使用 set... 來命名其設(shè)置該指針的方法,且不要 retain 集合對象砸烦。比如上面的 insertLayerManager:atIndex: 這種情形弃鸦,NSLayoutManager 類使用如下方法:
- (void) setTextStorage:(NSTextStorage *)textStorage;
- (NSTextStorage *)textStorage;
3.通常你不會直接調(diào)用 setTextStorage:,而是覆寫它幢痘。
- 另一個關(guān)于集合約定的例子來自 NSWindow 類:
- (void)addChildWindow:(NSWindow *)childWin ordered:(NSWindowOrderingMode)place;
- (void)removeChildWindow:(NSWindow *)childWin;
- (NSArray *)childWindows;
- (NSWindow *)parentWindow;
- (void)setParentWindow:(NSWindow *)window;
前綴
類名使用兩到三個字母的前綴 [Apple] [General]
Objective-C 沒有其他語言那種內(nèi)置的命名空間機(jī)制唬格。所以,在命名類和協(xié)議時應(yīng)使用前綴颜说。Apple宣稱其保留使用所有“兩字母前綴”的權(quán)利购岗。所以我們理論上最好選用三個字母作為前綴。然而门粪,大部分的項(xiàng)目都使用兩字母前綴 喊积,甚至像 AFNetworking 和 SDWebImage。所以玄妈,二到三字母的前綴都是可以的乾吻。蘋果公司的私有類會在前綴前加單下劃線,用戶的私有類不需要也不能用這樣的前綴作為標(biāo)識符拟蜻。Google 對前綴的建議是:應(yīng)用層的代碼绎签,應(yīng)該盡量避免不必要的前綴(如果項(xiàng)目擁有許多獨(dú)立的業(yè)務(wù)模塊,應(yīng)用層也可以用前綴來當(dāng)做命名空間來避免命名沖突)酝锅。為每個類都添加相同的前綴無助于可讀性诡必。當(dāng)編寫的代碼期望在不同應(yīng)用程序間復(fù)用時,才應(yīng)使用前綴搔扁。例如爸舒,Coding 的源碼就沒有加前綴,而那些開源庫的代碼基本都有前綴稿蹲。給私有變量加下劃線前綴 [General]
我們使用屬性時Xcode會自動為我們在實(shí)現(xiàn)文件中合成以下劃線開頭的成員變量扭勉。所以在我們直接聲明不公開的成員變量時也應(yīng)該以下劃線開頭。給私有方法加前綴 [Apple] [General]
私有方法應(yīng)該使用前綴進(jìn)行標(biāo)示來避免子類命名沖突场绿。蘋果公司喜歡用單下劃線作為私有方法的前綴剖效。所以其在官方文檔中強(qiáng)調(diào)嫉入,開發(fā)者不應(yīng)該用單下劃線作為前綴焰盗。這里《Effective Objective-C 2.0》的作者 Matt Galloway的習(xí)慣是使用"p_"作為前綴。自己用過"__"和"m_"咒林,后來又改為"p_"熬拒。然而倔強(qiáng)的 YYKit 就是要用單下劃線作為前綴。如果你有時間像大神一樣去掃描項(xiàng)目中的 API 并確保沒有對系統(tǒng) API 產(chǎn)生影響垫竞,你也可以這樣用澎粟,畢竟這是最便捷美觀的方式蛀序。也許你已經(jīng)受到大神的感召也準(zhǔn)備這樣使用(比如我),那只要你命名時別使用那些常用的詞匯即可活烙。比如徐裸,如果你想重置 viewController 而使用"_resetViewController"的私有方法名,那么恭喜你命中了系統(tǒng)的私有 API啸盏。蘋果公司建議私有方法的前綴具有唯一性即可重贺,如基于你公司的名稱,或工程的名稱回懦,并以“XX_”形式給出气笙。比如你的工程名為"Byte Flogger",那么就可以是“BF_addObject:”怯晕。但這樣太丑了潜圃。常量名(如宏定義、枚舉舟茶、靜態(tài)局部變量等)應(yīng)該以小寫字母 k 開頭谭期,如:kInvalidHandle,kWritePerm稚晚。 [Google] [General]
枚舉中的常量應(yīng)使用與枚舉的名稱作為前綴崇堵。 [General]
typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {
UIViewAnimationCurveEaseInOut, // slow at beginning and end
UIViewAnimationCurveEaseIn, // slow at beginning
UIViewAnimationCurveEaseOut, // slow at end
UIViewAnimationCurveLinear
};
頭文件 [Google] [Apple] [General]
聲明孤立的類或協(xié)議:將孤立的類或協(xié)議聲明放置在單獨(dú)的頭文件中,該頭文件名稱與類或協(xié)議同名客燕。例如:頭文件 NSApplication.h 聲明 NSApplication 類鸳劳。
聲明相關(guān)聯(lián)的類或協(xié)議:將相關(guān)聯(lián)的聲明(類,類別及協(xié)議) 放置在一個頭文件中也搓,該頭文件名稱與主要的類/類別/協(xié)議的名字相同赏廓。例如:
頭文件 NSString.h 聲明 NSString 和 NSMutableString 類
頭文件 NSLock.h 聲明 NSLocking 協(xié)議和 NSLock, NSConditionLock, NSRecursiveLock 類包含框架頭文件:每個框架應(yīng)該包含一個與框架同名的頭文件,該頭文件包含該框架所有公開的頭文件傍妒。例如:頭文件 Foundation.h 包含框架 Foundation.framework 的所有頭文件幔摸。
為已有框架中的某個類擴(kuò)展 API:如果要在一個框架中聲明屬于另一個框架某個類的范疇類的方法,該頭文件的命名形式為:原類名+“Additions”颤练。例如:Application Kit 中的 NSBundleAdditions.h既忆。
相關(guān)聯(lián)的函數(shù)與數(shù)據(jù)類型:將相聯(lián)的函數(shù),常量嗦玖,結(jié)構(gòu)體以及其他數(shù)據(jù)類型放置到一個頭文件中患雇,并以合適的名字命名。如 Application Kit 中的 NSGraphics.h宇挫。
異常和通知 [Google] [Apple] [General]
- 異常
雖然你可以處于任何目的而使用異常(由 NSException 類及相關(guān)類實(shí)現(xiàn))苛吱,Cocoa 通常不使用異常來處理常規(guī)的,可預(yù)料的錯誤器瘪。在這些情形下翠储,使用諸如 nil, NULL, NO或錯誤代碼之類的返回值绘雁。異常的典型應(yīng)用類似數(shù)組越界之類的編程錯誤。異常由具有如下形式的全局 NSString 對象標(biāo)識:
[Prefix] + UniquePartOfName + Exception
UniquePartOfName 部分是有連續(xù)的首字符大寫的單詞組成援所。例如:
NSColorListIOException
NSColorListNotEditableException
NSDraggingException
NSFontUnavailableException
NSIllegalSelectorException
- 通知
如果一個類有委托庐舟,那它的大部分通知可能由其委托的委托方法來處理。這些通知的名稱應(yīng)該能夠反應(yīng)其響應(yīng)的委托方法住拭。比如继阻,當(dāng)應(yīng)用程序提交如下通知時,全局 NSApplication 對象的委托會注冊從而能夠接收 applicaitonDidBecomeActive: 消息废酷。
NSApplicationDidBecomeActiveNotification
通知由具有如下形式的全局 NSString 對象標(biāo)識:
[相關(guān)聯(lián)類的名稱] + [Did 或 Will] + [UniquePartOfName] + Notification
例如:
NSApplicationDidBecomeActiveNotification
NSWindowDidMiniaturizeNotification
NSTextViewDidChangeSelectionNotification
NSColorPanelColorDidChangeNotification
附錄 [Google] [Apple] [General]
- 可接受的縮略語
在設(shè)計(jì)編程接口時瘟檩,通常名稱不要縮寫。然而澈蟆,下面列出的縮寫要么是固定下來的要么是過去被廣泛使用的墨辛,所以你可以繼續(xù)使用。關(guān)于縮寫有一些額外的注意事項(xiàng):
- 標(biāo)準(zhǔn) C 庫中長期使用的縮寫形式是可以接受的趴俘。如:"alloc"睹簇,"getc"。
- 你可以在參數(shù)名中更自由地使用縮寫寥闪。如:imageRep太惠,col(column),obj疲憋,otherWin凿渊。
alloc Allocate
msg Message
alt Alternate
nib Interface Builder archive
app Application
pboard Pasteboard
calc Calculate
rect Rectangle
dealloc Deallocate
Rep Representation
func Function
temp Temporary
horiz Horizontal
vert Vertical
info Information
init Initialize
max Maximum
ASCII,PDF缚柳,XML埃脏,HTML,URL秋忙,RTF彩掐,HTTP,TIFF
JPG灰追,GIF堵幽,LZW,ROM弹澎,RGB朴下,CMYK,MIDI裁奇,F(xiàn)TP
博客:xuyafei.cn
簡書:jianshu.com/users/2555924d8c6e
微博:weibo.com/xuyafei86
Github:github.com/xiaofei86