[iOS翻譯]Cocoa編碼規範

 
 
簡介:
本文整理自Apple文檔《Coding Guidelines for Cocoa》。這份文檔原意是給Cocoa框架、插件及公共API開發者提供一些編碼指導,實質上至關於Apple內部的編碼規範。在多人協做時,一份統一的代碼規範大大減小開發者之間的溝通成本,極力推薦。 
 
目錄:
1、代碼命名基礎
2、方法
3、函數
4、Property及其餘
5、縮寫  
 
 
 
1、代碼命名基礎

1.通用原則git

1.1 清晰編程

  • 儘可能清晰又簡潔,沒法兩全時清晰更重要

Codeapp

Commentary框架

insertObject:atIndex:less

ide

insert:at:函數

不清晰,insert什麼?at表示什麼?ui

removeObjectAtIndex:編碼

spa

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.classprotocol命名

  • 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 


 

2、方法

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」 命名

    ◦    參數類型裏就已代表它是不是一個指針

 

  • 避免只有一到二個字母的參數名

 

  • 避免只有幾個字母的縮寫
    ...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保留這一使用方式

    ◦    由於如果你的私有方法名已被Apple使用,覆蓋它將會產生極難追蹤的BUG

 

  • 若是繼承自大型Cocoa框架(如UIView),請確保子類的私有方法名與父類不同

    ◦    能夠爲私有方法加一個前綴,如公司名或項目名:XX_

      ▪    例如你的項目叫作Byte Flogger,那麼前綴多是:BF_addObject

    ◦    總之,爲子類的私有方法添加前綴是爲了避免覆蓋其父類的私有方法


 

3、函數

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

    ◦    你使用的類和常量擁有相同的前綴

    ◦    前綴後的首字母大寫

 

  • 許多函數名以描述其做用的動詞開始
    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)

 

 

4、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之類的東西建立一個匿名枚舉 
    enum { 
        NSBorderlessWindowMask       = 0, 
        NSTitledWindowMask           = 1 << 0,
        NSClosableWindowMask         = 1 << 1,
        NSMiniaturizableWindowMask   = 1 << 2, 
        NSResizableWindowMask         = 1 << 3
    };   

 

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

  

 

5、縮寫

  • 設計編程接口時一般不該使用縮寫,但下列已被普遍使用的縮寫名稱除外

    ◦    標準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

相關文章
相關標籤/搜索