注:本文轉(zhuǎn)載自http://www.cocoachina.com/ios/20150908/13335.html, 非作者原創(chuàng),用于個(gè)人隨時(shí)查閱,特此聲明!!!
簡(jiǎn)介:
本文整理自Apple文檔《Coding Guidelines for Cocoa》。這份文檔原意是給Cocoa框架、插件及公共API開發(fā)者提供一些編碼指導(dǎo),實(shí)質(zhì)上相當(dāng)于Apple內(nèi)部的編碼規(guī)范。在多人協(xié)作時(shí),一份統(tǒng)一的代碼規(guī)范大大減少開發(fā)者之間的溝通成本,極力推薦。
目錄:
一、代碼命名基礎(chǔ)
二、方法
三、函數(shù)
四、Property及其他
五、縮寫
一、代碼命名基礎(chǔ)
1.通用原則
1.1 清晰
盡量清晰又簡(jiǎn)潔,無法兩全時(shí)清晰更重要
通常不應(yīng)縮寫名稱,即使方法名很長也應(yīng)完整拼寫
你可能認(rèn)為某個(gè)縮寫眾所周知,但其實(shí)未必,特別是你周圍的開發(fā)者語言文化背景不同時(shí)
有一些歷史悠久的縮寫還是可以使用的,詳見第五章
API命名避免歧義,例如一個(gè)方法名有多種理解
1.2 一致
盡力保持Cocoa編程接口命名一致
如果有疑惑,請(qǐng)瀏覽當(dāng)前頭文件或者參考文檔
當(dāng)某個(gè)類的方法使用了多態(tài)時(shí),一致性尤其重要
不同類里,功能相同的方法命名也應(yīng)相同
1.3 避免自引用(self Reference)
命名不應(yīng)自引用
這里的自引用指的是在詞尾引用自身
Mask與Notification忽略此規(guī)則
2.前綴
前綴是編程接口命名的重要部分,它們區(qū)分了軟件的不同功能區(qū)域:
前綴可以防止第三方開發(fā)者與Apple的命名沖突
同樣可以防止Apple內(nèi)部的命名沖突
前綴有指定格式
它由二到三個(gè)大寫字母組成,不使用下劃線和子前綴
命名類、協(xié)議、函數(shù)、常量和typedef結(jié)構(gòu)體時(shí)使用前綴
方法名不使用前綴(因?yàn)樗嬖谟谔囟惖拿臻g中)
結(jié)構(gòu)體字段不使用前綴
[圖片上傳中。。。(7)]
3.書寫約定
在命名API元素時(shí), 使用駝峰命名法(如runTheWordsTogether),并注意以下書寫約定:
方法名
小寫第一個(gè)字母,大寫之后所有單詞的首字母,不使用前綴
如果方法名以一個(gè)眾所周知的大寫縮略詞開始,該規(guī)則不適用
如TIFFRepresentation (NSImage)
1
fileExistsAtPath:isDirectory:
函數(shù)及常量名
使用與其關(guān)聯(lián)類相同的前綴,并大寫首字母
1
2
NSRunAlertPanel
NSCellDisabled
標(biāo)點(diǎn)符號(hào)
由多個(gè)單詞組成的名稱,別使用標(biāo)點(diǎn)符號(hào)作為名稱的一部分
分隔符(下劃線、破折號(hào)等)也不能使用
避免使用下劃線作為私有方法的前綴,Apple保留這一方式的使用
強(qiáng)行使用可能會(huì)導(dǎo)致命名沖突,即Apple已有的方法被覆蓋,這會(huì)導(dǎo)致災(zāi)難性后果
實(shí)例變量使用下劃線作為前綴還是允許的
4.class與protocol命名
class
class的名稱應(yīng)該包含一個(gè)名詞,用以表明這個(gè)類是什么(或者做了什么),并擁有合適的前綴
如NSString、NSDate、NSScanner、UIApplication、UIButton
不關(guān)聯(lián)class的protocol
大多數(shù)protocol聚集了一堆相關(guān)方法,并不關(guān)聯(lián)class
這種protocol使用ing形式以和class區(qū)分開來
關(guān)聯(lián)class的protocol
一些protoco聚集了一堆無關(guān)方法,并試圖與某個(gè)class關(guān)聯(lián)在一起,由這個(gè)class來主導(dǎo)
這種protocol與class同名
如NSObject protocol
5.頭文件
頭文件的命名極其重要,因?yàn)樗梢灾赋鲱^文件包含的內(nèi)容:
聲明一個(gè)孤立的class或protocol
將聲明放入單獨(dú)的文件
使頭文件名與聲明的class/protocol相同
[圖片上傳中。。。(9)]
聲明關(guān)聯(lián)的class或protocol
將關(guān)聯(lián)的聲明(class/category/protocol)放入同一個(gè)頭文件
頭文件名與主要的class/category/protocol相同
[圖片上傳中。。。(10)]
Framework頭文件
每個(gè)framework都應(yīng)該有一個(gè)同名頭文件
Include了框架內(nèi)其他所有頭文件
添加API到另一個(gè)framework
如果要在一個(gè)framework中為另一個(gè)framework的class catetgory添加方法,加上單詞“Additions”
如Application Kit的NSBundleAdditions.h 文件
關(guān)聯(lián)的函數(shù)、數(shù)據(jù)類型
如果你有一組關(guān)聯(lián)的函數(shù)、常量、結(jié)構(gòu)體或其他數(shù)據(jù)類型,將它們放到一個(gè)名字合適的頭文件中
如Application Kit的NSGraphics.h
二、方法
1.通用原則
以小寫字母開始,之后單詞的首字母大寫
以眾所周知的縮寫開始可以大寫,如TIFF、PDF
私有方法可以加前綴
如果方法代表對(duì)象接收的動(dòng)作,以動(dòng)詞開始
不要使用 do 或 does 作為名字的一部分,因?yàn)橹鷦?dòng)詞在這里很少有實(shí)際意義
同樣的,也別在動(dòng)詞之前使用副詞和形容詞
1
2
(void)invokeWithTarget:(id)target;
(void)selectTabViewItem:(NSTabViewItem *)tabViewItem
如果方法返回接收者的屬性,以 接收者 + 接收的屬性 命名
除非間接返回多個(gè)值,否則不要使用 get 單詞(為了與accessor methods區(qū)分)
[圖片上傳中。。。(12)]
在所有參數(shù)之前使用關(guān)鍵字
[圖片上傳中。。。(13)]
確保參數(shù)之前的關(guān)鍵字充分描述了參數(shù)
[圖片上傳中。。。(14)]
創(chuàng)建自定義 init 方法時(shí),記得指明關(guān)聯(lián)的元素
[圖片上傳中。。。(15)]
不要使用 and 來連接作為接收者屬性的關(guān)鍵字
雖然下面的例子使用 and 看似不錯(cuò),但是一旦參數(shù)非常多時(shí)就容易出現(xiàn)問題
[圖片上傳中。。。(16)]
除非方法描述了兩個(gè)獨(dú)立的操作,才使用 and 來連接它們
[圖片上傳中。。。(17)]
2.getter和setter方法(Accessor Methods)
如果property表示為名詞,格式如下
(type)noun;
(void)setNoun:(type)aNoun;
(BOOL)isAdjective;
1
2
(NSString *)title;
(void)setTitle:(NSString *)aTitle;
如果property表示為形容詞,格式如下
(BOOL)isAdjective;
(void)setAdjective:(BOOL)flag;
1
2
(BOOL)isEditable;
(void)setEditable:(BOOL)flag;
如果property表示為動(dòng)詞,格式如下(動(dòng)詞用一般現(xiàn)在時(shí))
(BOOL)verbObject;
(void)setVerbObject:(BOOL)flag;
1
2
(BOOL)showsAlpha;
(void)setShowsAlpha:(BOOL)flag;
不要把動(dòng)詞的過去分詞形式當(dāng)作形容詞使用
[圖片上傳中。。。(18)]
你可能使用情態(tài)動(dòng)詞(can、should、will等)來增加可讀性,不過不要使用 do或 does
[圖片上傳中。。。(19)]
只有方法需要間接返回多個(gè)值的情況下才使用 get
像這種接收多個(gè)參數(shù)的方法應(yīng)該能夠傳入nil,因?yàn)檎{(diào)用者未必對(duì)每個(gè)參數(shù)都感興趣
[圖片上傳中。。。(20)]
3.Delegate方法
以發(fā)送消息的對(duì)象開始
省略了前綴的類名和首字母小寫
1
2
(BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row;
(BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
以發(fā)送消息的對(duì)象開始的規(guī)則不適用下列兩種情況
只有一個(gè)sender參數(shù)的方法
1
- (BOOL)applicationOpenUntitledFile:(NSApplication *)sender;
響應(yīng)notification的方法(方法的唯一參數(shù)就是notification)
1
- (void)windowDidChangeScreen:(NSNotification *)notification;
使用單詞 did 和 will 來通知delegate
did 表示某些事已發(fā)生
will 表示某些事將要發(fā)生
1
2
(void)browserDidScroll:(NSBrowser *)sender;
(NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window;
詢問delegate是否可以執(zhí)行某個(gè)行為時(shí)可以使用 did 或 will,不過 should 更完美
1
- (BOOL)windowShouldClose:(id)sender;
**4.集合方法 **
為了管理集合中的元素,集合應(yīng)該有這幾個(gè)方法
(void)addElement:(elementType)anObj;
(void)removeElement:(elementType)anObj;
(NSArray *)elements;
1
2
3
(void)addLayoutManager:(NSLayoutManager *)obj;
(void)removeLayoutManager:(NSLayoutManager *)obj;
(NSArray *)layoutManagers;
如果集合是無序的,返回一個(gè)NSSet比NSarray更好
如果需要在集合中的特定位置插入元素,使用類似下面的方法
1
2
(void)insertLayoutManager:(NSLayoutManager *)obj atIndex:(int)index;
(void)removeLayoutManagerAtIndex:(int)index;
其他集合方法示例
1
2
3
4
5
(void)addChildWindow:(NSWindow *)childWin ordered:(NSWindowOrderingMode)place;
(void)removeChildWindow:(NSWindow *)childWin;
(NSArray *)childWindows;
(NSWindow *)parentWindow;
(void)setParentWindow:(NSWindow *)window;
**5.方法參數(shù) **
參數(shù)名以小寫字母開始,之后的單詞首字母大寫
1
如:removeObject:(id)anObject
別使用 ”pointer” 或 ”ptr” 命名
參數(shù)類型里就已表明它是否是一個(gè)指針
避免只有一到二個(gè)字母的參數(shù)名
避免只有幾個(gè)字母的縮寫
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...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
6.私有方法
不要使用下劃線作為私有方法的前綴,Apple保留這一使用方式
因?yàn)槿羰悄愕乃接蟹椒驯籄pple使用,覆蓋它將會(huì)產(chǎn)生極難追蹤的BUG
如果繼承自大型Cocoa框架(如UIView),請(qǐng)確保子類的私有方法名與父類不一樣
可以為私有方法加一個(gè)前綴,如公司名或項(xiàng)目名:XX_
例如你的項(xiàng)目叫做Byte Flogger,那么前綴可能是:BF_addObject
總之,為子類的私有方法添加前綴是為了不覆蓋其父類的私有方法
三、函數(shù)
函數(shù)的命名類似方法,但有兩點(diǎn)要注意
你使用的類和常量擁有相同的前綴
前綴后的首字母大寫
許多函數(shù)名以描述其作用的動(dòng)詞開始
1
2
NSHighlightRect
NSDeallocateObject
查詢屬性的函數(shù)有進(jìn)一步的命名規(guī)則
如果函數(shù)返回首個(gè)參數(shù)的屬性,省略動(dòng)詞
1
2
unsigned int NSEventMaskFromType(NSEventType type)
float NSHeight(NSRect aRect)
如果通過reference返回了值,使用 “Get”
1
const char *NSGetSizeAndAlignment(const char *typePtr, unsigned int *sizep, unsigned int *alignp)
如果返回的是boolean值,應(yīng)該靈活使用動(dòng)詞
1
BOOL NSDecimalIsNotANumber(const NSDecimal *decimal)
四、Property及其他
1.Property與實(shí)例變量
1.1 Property
Property命名規(guī)則與第二章accessor methods一樣(因?yàn)閮烧呔o密聯(lián)系)
如果property表示為一個(gè)名詞或動(dòng)詞,格式如下
@property (…) 類型 名詞/動(dòng)詞 ;
1
2
@property (strong) NSString *title;
@property (assign) BOOL showsAlpha;
如果property表示為一個(gè)形容詞
可省略 ”is” 前綴
但要指定getter方法的慣用名稱
1
@property (assign, getter=isEditable) BOOL editable;
1.2 實(shí)例變量
通常不應(yīng)該直接訪問實(shí)例變量
init、dealloc、accessor methods等方法內(nèi)部例外
實(shí)例變量以下劃線 “_” 開始
確保實(shí)例變量描述了所存儲(chǔ)的屬性
1
2
3
@implementation MyClass {
BOOL _showsTitle;
}
如果想要修改property的實(shí)例變量名,使用 @synthesize語句
1
2
@implementation MyClass
@synthesize showsTitle=_showsTitle;
為一個(gè)class添加實(shí)例變量時(shí),有幾點(diǎn)需要注意:
避免聲明公有實(shí)例變量
開發(fā)者關(guān)注的應(yīng)該是對(duì)象接口,而不是其數(shù)據(jù)細(xì)節(jié)
你可以通過使用property來避免聲明實(shí)例變量
如果需要聲明實(shí)例變量,指定關(guān)鍵字@private 或 @protected
如果你希望子類可以直接訪問某個(gè)實(shí)例變量,使用 @protected 關(guān)鍵字
如果一個(gè)實(shí)例變量是某個(gè)類可訪問的屬性,確保寫了accessor methods
如果有可能,還是使用property
**2.常量 **
2.1 枚舉常量
使用枚舉來關(guān)聯(lián)一組integer常量
枚舉常量和typedef遵循函數(shù)的命名規(guī)范,下面的例子是 NSMatrix.h
1
2
3
4
5
6
typedef enum _NSMatrixMode {
NSRadioModeMatrix = 0,
NSHighlightModeMatrix = 1,
NSListModeMatrix = 2,
NSTrackModeMatrix = 3
} NSMatrixMode;
你可以為bit masks之類的東西創(chuàng)建一個(gè)匿名枚舉
1
2
3
4
5
6
7
enum {
NSBorderlessWindowMask = 0,
NSTitledWindowMask = 1 << 0,
NSClosableWindowMask = 1 << 1,
NSMiniaturizableWindowMask = 1 << 2,
NSResizableWindowMask = 1 << 3
};
**2.2 使用const關(guān)鍵字的常量 **
使用const關(guān)鍵字來創(chuàng)建一個(gè)float常量
你可以使用const關(guān)鍵字來創(chuàng)建一個(gè)與其他常量不相關(guān)的integer常量,否則,使用枚舉
使用const關(guān)鍵字的常量也遵循函數(shù)的命名規(guī)則
1
const float NSLightGray;
**2.3 其他常量類型 **
通常不應(yīng)使用 #define 預(yù)編譯指令來創(chuàng)建常量
integer常量,使用枚舉
float常量,使用 const 修飾符
對(duì) #define 預(yù)編譯指令,大寫所有字母
比如 DEBUG 判斷
1
ifdef DEBUG
注意宏命令的字首和字尾都有雙下劃線
1
MACH
定義NSString常量來作為Notification和Key值
這樣做可以有效防止拼寫錯(cuò)誤
1
APPKIT_EXTERN NSString *NSPrintCopies;
3.Notifications與Exceptions
**3.1 Notifications **
Notification的格式
1
[Name of associated class] + [Did | Will] + [UniquePartOfName] + Notification
1
2
3
4
NSApplicationDidBecomeActiveNotification
NSWindowDidMiniaturizeNotification
NSTextViewDidChangeSelectionNotification
NSColorPanelColorDidChangeNotification
**3.2 Exceptions **
Exception的格式
1
[Prefix] + [UniquePartOfName] + Exception
1
2
3
4
5
NSColorListIOException
NSColorListNotEditableException
NSDraggingException
NSFontUnavailableException
NSIllegalSelectorException
五、縮寫
設(shè)計(jì)編程接口時(shí)通常不應(yīng)使用縮寫,但下列已被廣泛使用的縮寫名稱除外
標(biāo)準(zhǔn)C庫中的縮寫名,如:alloc、init
參數(shù)名可自由使用縮寫,如:imageRep、col、obj、otherWin
[圖片上傳中。。。(21)]
[圖片上傳中。。。(22)]