天天看點

Cocoa編碼規範

簡介: 本文整理自Apple文檔《Coding Guidelines for Cocoa》。這份文檔原意是給Cocoa架構、插件及公共API開發者提供一些編碼指導,實質上相當于Apple内部的編碼規範。在多人協作時,一份統一的代碼規範大大減少開發者之間的溝通成本,極力推薦。    目錄: 一、代碼命名基礎 二、方法 三、函數 四、Property及其他 五、縮寫         一、代碼命名基礎

1.通用原則

1.1 清晰

  • 盡量清晰又簡潔,無法兩全時清晰更重要
Code Commentary
insertObject:atIndex:
insert:at: 不清晰,insert什麼?at表示什麼?
removeObjectAtIndex:
removeObject: √ ,因為參數指明了移除對象
remove: 不清晰,要移除什麼?
  • 通常不應縮寫名稱,即使方法名很長也應完整拼寫

    ◦    你可能認為某個縮寫衆所周知,但其實未必,特别是你周圍的開發者語言文化背景不同時

    ◦    有一些曆史悠久的縮寫還是可以使用的,詳見第五章

Code Commentary
destinationSelection
destSel 不清晰
setBackgroundColor:
setBkgdColor: 不清晰
  • API命名避免歧義,例如一個方法名有多種了解
Code Commentary
sendPort 發送還是傳回一個port ?
displayName 顯示一個名字還是傳回UI界面上的标題?

1.2 一緻

  • 盡力保持Cocoa程式設計接口命名一緻

    ◦    如果有疑惑,請浏覽目前頭檔案或者參考文檔

  • 當某個類的方法使用了多态時,一緻性尤其重要

    ◦    不同類裡,功能相同的方法命名也應相同

Code Commentary
- (NSInteger)tag 定義在 NSView, NSCell, NSControl.
- (void)setStringValue:(NSString *) 定義在許多Cocoa類裡

1.3 避免自引用(self Reference)

  • 命名不應自引用

    ◦   這裡的自引用指的是在詞尾引用自身

Code Commentary
NSString
NSStringObject 自引用,所有NSString都是對象,不用額外聲明
  • Mask與Notification忽略此規則
Code Commentary
NSUnderlineByWordMask
NSTableViewColumnDidMoveNotification

2.字首

       字首是程式設計接口命名的重要部分,它們區分了軟體的不同功能區域:

  • 字首可以防止第三方開發者與Apple的命名沖突

    ◦    同樣可以防止Apple内部的命名沖突

  • 字首有指定格式

    ◦    它由二到三個大寫字母組成,不使用下劃線和子字首

  • 命名類、協定、函數、常量和typedef結構體時使用字首

    ◦    方法名不使用字首(因為它存在于特定類的命名空間中)

    ◦    結構體字段不使用字首 

Prefix Cocoa Framework
NS Foundation
NS Application Kit
AB Address Book
IB Interface Builder

3.書寫約定

  在命名API元素時, 使用駝峰命名法(如runTheWordsTogether),并注意以下書寫約定:

  • 方法名

    ◦    小寫第一個字母,大寫之後所有單詞的首字母,不使用字首

    ◦    如果方法名以一個衆所周知的大寫縮略詞開始,該規則不适用

      ▪    如TIFFRepresentation (NSImage)

fileExistsAtPath:isDirectory:      
  •  函數及常量名

    ◦    使用與其關聯類相同的字首,并大寫首字母

NSRunAlertPanel
NSCellDisabled       
  •  标點符号

    ◦    由多個單詞組成的名稱,别使用标點符号作為名稱的一部分

      ▪    分隔符(下劃線、破折号等)也不能使用

  • 避免使用下劃線作為私有方法的字首,Apple保留這一方式的使用

    ◦    強行使用可能會導緻命名沖突,即Apple已有的方法被覆寫,這會導緻災難性後果

    ◦    執行個體變量使用下劃線作為字首還是允許的

4.class與protocol命名

  • class

    ◦    class的名稱應該包含一個名詞,用以表明這個類是什麼(或者做了什麼),并擁有合适的字首

      ▪    如NSString、NSDate、NSScanner、UIApplication、UIButton

  • 不關聯class的protocol

    ◦    大多數protocol聚集了一堆相關方法,并不關聯class

    ◦    這種protocol使用ing形式以和class區分開來

Code Commentary
NSLocking
NSLock 不好,看起來像是一個class
  • 關聯class的protocol

    ◦    一些protoco聚集了一堆無關方法,并試圖與某個class關聯在一起,由這個class來主導

    ◦    這種protocol與class同名

      ▪    如NSObject protocol

5.頭檔案

  頭檔案的命名極其重要,因為它可以指出頭檔案包含的内容:

  • 聲明一個孤立的class或protocol

    ◦    将聲明放入單獨的檔案

    ◦    使頭檔案名與聲明的class/protocol相同

Header file Declares
NSLocale.h 包含NSLocale class.
  • 聲明關聯的class或protocol

    ◦    将關聯的聲明(class/category/protocol)放入同一個頭檔案

    ◦    頭檔案名與主要的class/category/protocol相同

Header file Declares
NSString.h 包含NSString和NSMutableString classes.
NSLock.h 包含NSLocking protocol 和 NSLock, NSConditionLock, NSRecursiveLock classes.
  • Framework頭檔案

    ◦    每個framework都應該有一個同名頭檔案

    ◦    Include了架構内其他所有頭檔案

Header file Framework
Foundation.h Foundation.framework.
  • 添加API到另一個framework

    ◦    如果要在一個framework中為另一個framework的class catetgory添加方法,加上單詞“Additions” 

      ▪    如Application Kit的NSBundleAdditions.h 檔案

  • 關聯的函數、資料類型

    ◦    如果你有一組關聯的函數、常量、結構體或其他資料類型,将它們放到一個名字合适的頭檔案中

      ▪    如Application Kit的NSGraphics.h 

二、方法

1.通用原則 

  • 以小寫字母開始,之後單詞的首字母大寫

    ◦    以衆所周知的縮寫開始可以大寫,如TIFF、PDF

    ◦    私有方法可以加字首

  • 如果方法代表對象接收的動作,以動詞開始

    ◦    不要使用 do 或 does 作為名字的一部分,因為助動詞在這裡很少有實際意義

    ◦    同樣的,也别在動詞之前使用副詞和形容詞

- (void)invokeWithTarget:(id)target;
- (void)selectTabViewItem:(NSTabViewItem *)tabViewItem        
  • 如果方法傳回接收者的屬性,以 接收者 + 接收的屬性 命名

    ◦   除非間接傳回多個值,否則不要使用 get 單詞(為了與accessor methods區分) 

- (NSSize)cellSize;
- (NSSize)calcCellSize;
- (NSSize)getCellSize;
  • 在所有參數之前使用關鍵字 

- (void)sendAction:(SEL)aSelector

              toObject:(id)anObject

            forAllCells:(BOOL)flag;

- (void)sendAction:(SEL)aSelector

                          :(id)anObject

                          :(BOOL)flag;

  • 確定參數之前的關鍵字充分描述了參數
- (id)viewWithTag:(NSInteger)aTag;
- (id)taggedView:(int)aTag;
  • 建立自定義 init 方法時,記得指明關聯的元素
- (id)initWithFrame:(CGRect)frameRect;

- (id)initWithFrame:(NSRect)frameRect

                   mode:(int)aMode

               cellClass:(Class)factoryId

      numberOfRows:(int)rowsHigh

 numberOfColumns:(int)colsWide;

  • 不要使用 and 來連接配接作為接收者屬性的關鍵字

    ◦  雖然下面的例子使用 and 看似不錯,但是一旦參數非常多時就容易出現問題

- (int)runModalForDirectory:(NSString *)path

                                   file:(NSString *)name

                               types:(NSArray *)fileTypes;

- (int)runModalForDirectory:(NSString *)path

                      andFile:(NSString *)name

                     andTypes:(NSArray *)fileTypes;

  • 除非方法描述了兩個獨立的操作,才使用 and 來連接配接它們

- (BOOL)openFile:(NSString *)fullPath

   withApplication:(NSString *)appName

    andDeactivate:(BOOL)flag;

2.getter和setter方法(Accessor Methods)

  • 如果property表示為名詞,格式如下

    ◦    - (type)noun;

    ◦    - (void)setNoun:(type)aNoun;  

    ◦    - (BOOL)isAdjective;

- (NSString *)title;
- (void)setTitle:(NSString *)aTitle;       
  • 如果property表示為形容詞,格式如下

    ◦    - (BOOL)isAdjective;

    ◦    - (void)setAdjective:(BOOL)flag;  

- (BOOL)isEditable; 
- (void)setEditable:(BOOL)flag;       
  • 如果property表示為動詞,格式如下(動詞用一般現在時)

    ◦    - (BOOL)verbObject;

    ◦    - (void)setVerbObject:(BOOL)flag;  

- (BOOL)showsAlpha;
- (void)setShowsAlpha:(BOOL)flag;       
  • 不要把動詞的過去分詞形式當作形容詞使用  
- (void)setAcceptsGlyphInfo:(BOOL)flag;
- (BOOL)acceptsGlyphInfo;
- (void)setGlyphInfoAccepted:(BOOL)flag;
- (BOOL)glyphInfoAccepted;
  • 你可能使用情态動詞(can、should、will等)來增加可讀性,不過不要使用 do或 does
- (void)setCanHide:(BOOL)flag;
- (BOOL)canHide;
- (void)setShouldCloseDocument:(BOOL)flag;
- (BOOL)shouldCloseDocument;
- (void)setDoesAcceptGlyphInfo:(BOOL)flag;
- (BOOL)doesAcceptGlyphInfo;
  • 隻有方法需要間接傳回多個值的情況下才使用 get

    ◦    像這種接收多個參數的方法應該能夠傳入nil,因為調用者未必對每個參數都感興趣

- (void)getLineDash:(float *)pattern

                    count:(int *)count

                   phase:(float *)phase;

NSBezierPath.

3.Delegate方法

  • 以發送消息的對象開始

    ◦   省略了字首的類名和首字母小寫

- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row; 
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;       
  • 以發送消息的對象開始的規則不适用下列兩種情況

    ◦   隻有一個sender參數的方法

- (BOOL)applicationOpenUntitledFile:(NSApplication *)sender;      

    ◦   響應notification的方法(方法的唯一參數就是notification)

- (void)windowDidChangeScreen:(NSNotification *)notification;      
  • 使用單詞 did 和 will 來通知delegate

    ◦     did 表示某些事已發生

    ◦     will 表示某些事将要發生

- (void)browserDidScroll:(NSBrowser *)sender;
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window;       
  • 詢問delegate是否可以執行某個行為時可以使用 did 或 will,不過 should 更完美  
- (BOOL)windowShouldClose:(id)sender;      

4.集合方法   

  • 為了管理集合中的元素,集合應該有這幾個方法

    ◦    - (void)addElement:(elementType)anObj;

    ◦    - (void)removeElement:(elementType)anObj;

    ◦    - (NSArray *)elements;

- (void)addLayoutManager:(NSLayoutManager *)obj;
- (void)removeLayoutManager:(NSLayoutManager *)obj;
- (NSArray *)layoutManagers;        
  • 如果集合是無序的,傳回一個NSSet比NSarray更好
  • 如果需要在集合中的特定位置插入元素,使用類似下面的方法
    - (void)insertLayoutManager:(NSLayoutManager *)obj atIndex:(int)index; 
    - (void)removeLayoutManagerAtIndex:(int)index;       
  • 其他集合方法示例
    - (void)addChildWindow:(NSWindow *)childWin ordered:(NSWindowOrderingMode)place;
    - (void)removeChildWindow:(NSWindow *)childWin;
    - (NSArray *)childWindows;
    - (NSWindow *)parentWindow;
    - (void)setParentWindow:(NSWindow *)window;       

5.方法參數 

  • 參數名以小寫字母開始,之後的單詞首字母大寫
    如:removeObject:(id)anObject      
  • 别使用 ”pointer” 或 ”ptr” 命名

    ◦    參數類型裡就已表明它是否是一個指針

  • 避免隻有一到二個字母的參數名
  • 避免隻有幾個字母的縮寫
    Cocoa編碼規範
    ...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      
    Cocoa編碼規範

6.私有方法

  • 不要使用下劃線作為私有方法的字首,Apple保留這一使用方式

    ◦    因為若是你的私有方法名已被Apple使用,覆寫它将會産生極難追蹤的BUG

  • 如果繼承自大型Cocoa架構(如UIView),請確定子類的私有方法名與父類不一樣

    ◦    可以為私有方法加一個字首,如公司名或項目名:XX_

      ▪    例如你的項目叫做Byte Flogger,那麼字首可能是:BF_addObject

    ◦    總之,為子類的私有方法添加字首是為了不覆寫其父類的私有方法

三、函數

  • 函數的命名類似方法,但有兩點要注意

    ◦    你使用的類和常量擁有相同的字首

    ◦    字首後的首字母大寫

  • 許多函數名以描述其作用的動詞開始
    NSHighlightRect
    NSDeallocateObject       
  • 查詢屬性的函數有進一步的命名規則

    ◦    如果函數傳回首個參數的屬性,省略動詞

unsigned int NSEventMaskFromType(NSEventType type) 
float NSHeight(NSRect aRect)       

    ◦    如果通過reference傳回了值,使用 “Get”

const char *NSGetSizeAndAlignment(const char *typePtr, unsigned int *sizep, unsigned int *alignp)      

    ◦    如果傳回的是boolean值,應該靈活使用動詞 

BOOL NSDecimalIsNotANumber(const NSDecimal *decimal)      

四、Property及其他

1.Property與執行個體變量

1.1 Property

  • Property命名規則與第二章accessor methods一樣(因為兩者緊密聯系)
  • 如果property表示為一個名詞或動詞,格式如下

    ◦    @property (…) 類型 名詞/動詞 ;

@property (strong) NSString *title;
@property (assign) BOOL showsAlpha;       
  • 如果property表示為一個形容詞

    ◦    可省略 ”is” 字首

    ◦    但要指定getter方法的慣用名稱

@property (assign, getter=isEditable) BOOL editable;      

1.2 執行個體變量

  • 通常不應該直接通路執行個體變量

    ◦    init、dealloc、accessor methods等方法内部例外

  • 執行個體變量以下劃線 “_” 開始

    ◦    確定執行個體變量描述了所存儲的屬性

@implementation MyClass {
   BOOL _showsTitle;
}       
  • 如果想要修改property的執行個體變量名,使用 @synthesize語句
    @implementation MyClass
    @synthesize showsTitle=_showsTitle;      

為一個class添加執行個體變量時,有幾點需要注意:

  • 避免聲明公有執行個體變量

    ◦    開發者關注的應該是對象接口,而不是其資料細節

    ◦    你可以通過使用property來避免聲明執行個體變量

  • 如果需要聲明執行個體變量,指定關鍵字@private 或 @protected

    ◦    如果你希望子類可以直接通路某個執行個體變量,使用 @protected 關鍵字

  • 如果一個執行個體變量是某個類可通路的屬性,確定寫了accessor methods

    ◦    如果有可能,還是使用property

2.常量  

2.1 枚舉常量

  • 使用枚舉來關聯一組integer常量  
  • 枚舉常量和typedef遵循函數的命名規範,下面的例子是 NSMatrix.h
    typedef enum _NSMatrixMode {
        NSRadioModeMatrix            = 0,
        NSHighlightModeMatrix       = 1,           
        NSListModeMatrix            = 2, 
        NSTrackModeMatrix           = 3
    } NSMatrixMode;       
  • 你可以為bit masks之類的東西建立一個匿名枚舉 
    Cocoa編碼規範
    enum { 
        NSBorderlessWindowMask       = 0, 
        NSTitledWindowMask           = 1 << 0,
        NSClosableWindowMask         = 1 << 1,
        NSMiniaturizableWindowMask   = 1 << 2, 
        NSResizableWindowMask         = 1 << 3
    };         
    Cocoa編碼規範

2.2 使用const關鍵字的常量 

  • 使用const關鍵字來建立一個float常量

    ◦    你可以使用const關鍵字來建立一個與其他常量不相關的integer常量,否則,使用枚舉

    ◦    使用const關鍵字的常量也遵循函數的命名規則 

const float NSLightGray;      

2.3 其他常量類型  

  • 通常不應使用 #define 預編譯指令來建立常量

    ◦    integer常量,使用枚舉

    ◦    float常量,使用 const 修飾符

  •  對 #define 預編譯指令,大寫所有字母

    ◦    比如 DEBUG 判斷

#ifdef DEBUG       
  • 注意宏指令的字首和字尾都有雙下劃線 
    __MACH__      
  • 定義NSString常量來作為Notification和Key值

    ◦   這樣做可以有效防止拼寫錯誤

APPKIT_EXTERN NSString *NSPrintCopies;      

3.Notifications與Exceptions

3.1 Notifications  

  • Notification的格式
    [Name of associated class] + [Did | Will] + [UniquePartOfName] + Notification      
NSApplicationDidBecomeActiveNotification
NSWindowDidMiniaturizeNotification 
NSTextViewDidChangeSelectionNotification
NSColorPanelColorDidChangeNotification      

3.2 Exceptions  

  • Exception的格式
    [Prefix] + [UniquePartOfName] + Exception      
NSColorListIOException
NSColorListNotEditableException
NSDraggingException  
NSFontUnavailableException
NSIllegalSelectorException      

五、縮寫

  • 設計程式設計接口時通常不應使用縮寫,但下列已被廣泛使用的縮寫名稱除外

    ◦    标準C庫中的縮寫名,如:alloc、init

    ◦    參數名可自由使用縮寫,如:imageRep、col、obj、otherWin

縮寫 全稱
alloc Allocate.
alt Alternate.
app Application.
calc Calculate.
dealloc Deallocate.
func Function.
horiz Horizontal.
info Information.
init Initialize.
int Integer
max Maximum.
min Minimum.
msg Message.
nib Interface Builder archive.
pboard Pasteboard.
rect Rectangle.
Rep Representation.
temp Temporary.
vert Vertical.
縮寫 全稱
ASCII American Standard Code for Information Interchange
PDF Portable Document Format
XML Extensible Markup Language
HTML HyperText Markup Language
URL Uniform Resource Locator
RTF Rich Text Format
HTTP HyperText Transfer Protocol
TIFF Tagged Image File Format
JPG/JPEG Joint Photographic Experts GROUP
PNG Portable Network Graphic Format
GIF Graphics Interchange Format
LZW Lempel Ziv Welch
ROM Read-Only Memory
RGB R(red)、G(green)、B(blue)
CMYK C:Cyan、M:Magenta、Y:Yellow、K:Key Plate(blacK)
MIDI Musical Instrument Digital Interface
FTP File Transfer Protocol

 本文轉載自:http://www.cnblogs.com/yangfaxian/p/4673894.html?sukey=a805c0b270074a06b8513acfc04338fb98e18e6592e6455019254895dbfd0bba457fb535e3d3314c00bae1b10f6409db