苹果 Cocoa 编码规范中文版

[Cocoa][译]苹果 Cocoa 编码规范中文版


官方文档: Coding Guidelines for Cocoa

 

> Code Naming Basics 代码命名基础

在面向对象软件库的设计过程中,开发人员经常忽视对类,方法,函数,常量以及其他编程接口元素的命名。本节讨论大多数Cocoa接口的一些命名约定。

>> General Principles 一般性原则

>>> Clarity 清晰性

● 最好是既清晰又简短,但不要为简短而丧失清晰性

代码

点评

destinationSelection

good

destSel

不清晰

setBackgroundColor:

good

setBkgdColor:

不清晰

你可能会认为某个缩写广为人知,但有可能并非如此,尤其是当你的代码被来自不同文化和语言背景的开发人员所使用时。

● 然而,你可以使用少数非常常见,历史悠久的缩写。请参考:”可接受的缩略名“一节

● 避免使用有歧义的 API 名称,如那些能被理解成多种意思的方法名称

代码

点评

- (int) tag

在 NSView, NSCell, NSControl 中有定义

- (void) setStringValue:(NSString *)

在许多 Cocoa classes 中有定义

请参考“方法参数”一节。

>>> No Self Reference 不要自我指涉

● 不要名称自我指涉

代码

点评

NSUnderlineByWordMask

okey

NSTableViewColumnDidMoveNotification

okey

>> Prefixes 前缀

前缀是名称的重要组成部分。它们可以区分软件的功能范畴。通常,软件会被打包成一个框架或多个紧密相关的框架(如 Foundation 和 Application Kit 框架)。前缀可以防止第三方开发者与苹果公司之间的命名冲突(同样也可防止苹果内部不同框架之间的命名冲突)

● 前缀有规定的格式。它由两到三个大写字符组成,不能使用下划线与子前缀

代码

点评

NSLocking

good

NSLock

糟糕,它看起来像类名

● 有些协议组合一些彼此无关的方法(这样做是避免创建多个独立的小协议)。这样的协议倾向于与某个类关联在一起,该类是协议的主要体现者。在这种情形,我们约定协议的名称与该类同名。NSObject 协议就是这样一个例子。这个协议组合一组彼此无关的方法,有用于查询对象在其类层次中位置的方法,有使之能调用特殊方法的方法以及用于增减引用计数的方法。由于 NSObject 是这些方法的主要体现者,所以我们用类的名称命名这个协议。

>> Header Files 头文件

头文件的命名方式很重要,我们可以根据其命名知晓头文件的内容。

● 声明孤立的类或协议:将孤立的类或协议声明放置在单独的头文件中,该头文件名称与类或协议同名

头文件

声明

NSString.h

NSString 和 NSMutableString 类

NSLock.h

NSLocking 协议和 NSLock, NSConditionLock, NSRecursiveLock 类

● 包含框架头文件:每个框架应该包含一个与框架同名的头文件,该头文件包含该框架所有公开的头文件。

- (NSSize) cellSize;

 对

- (NSSize) calcCellSize;

 错

- (NSSize) getCellSize;

 错

● 参数要用描述该参数的关键字命名

- (id) viewWithTag:(int)aTag;

 对

- (id) taggedView:(int)aTag;

 错

● 细化基类中的已有方法:创建一个新方法,其名称是在被细化方法名称后面追加参数关键词

- (int) runModalForDirectory:(NSString *)path file:(NSString *)name types:(NSArray *)fileTypes;

 对

- (int) runModalForDirectory:(NSString *)path addFile:(NSString *)name addTypes:(NSArray *)fileTypes;

 错

虽然上面的例子中使用 add 看起来也不错,但当你方法有太多参数关键字时就有问题。

● 如果方法描述两种独立的行为,使用 and 来串接它们

- (void) setAcceptsGlyphInfo:(BOOL)flag;

 对

- (BOOL) acceptsGlyphInfo;

 对

- (void) setGlyphInfoAccepted:(BOOL)flag;

 错

- (BOOL) glyphInfoAccepted;

 错

● 可以使用情态动词(can, should, will 等)来提高清晰性,但不要使用 do 或 does

- (void) getLineDash:(float *)pattern count:(int *)count phase:(float *)phase;

 NSBezierPath

像上面这样的方法,在其实现里应允许接受 NULL 作为其 in/out 参数,以表示调用者对一个或多个返回值不感兴趣。

>> Delegate Methods 委托方法

委托方法是那些在特定事件发生时可被对象调用,并声明在对象的委托类中的方法。它们有独特的命名约定,这些命名约定同样也适用于对象的数据源方法。

● 名称以标示发送消息的对象的类名开头,省略类名的前缀并小写类第一个字符

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

● 上面的那条规则也不适用于响应通知的方法。在这种情况下,方法的唯一参数表示通知对象

- (void) browserDidScroll:(NSBrowser *)sender;

- (NSUndoManager *) windowWillReturnUndoManager:(NSWindow *)window;

● 用于询问委托对象可否执行某操作的方法名中可使用 did 或 will,但最好使用 should 

- (void) addElement:(elementType)adObj;

- (void) removeElement:(elementType)anObj;

- (NSArray *)elements;

例如:

- (void) insertElement:(elementType)anObj atIndex:(int)index;

- (void) removeElementAtIndex:(int)index;

集合方法的实现要考虑如下细节:

● 以上集合类方法通常负责管理元素的所有者关系,在 add 或 insert 的实现代码里会 retain 元素,在 remove 的实现代码中会 release 元素

● 当被插入的对象需要持有指向集合对象的指针时,通常使用 set... 来命名其设置该指针的方法,且不要 retain 集合对象。比如上面的 insertLayerManager:atIndex: 这种情形,NSLayoutManager 类使用如下方法:

- (void) addChildWindow:(NSWindow *)childWin ordered:(NSWindowOrderingMode)place;

- (void) removeChildWindow:(NSWindow *)childWin;

- (NSArray *)childWindows;

- (NSWindow *) parentWindow;

- (void) setParentWindow:(NSWindow *)window;

>> Method Arguments 方法参数

命名方法参数时要考虑如下规则:

● 如同方法名,参数名小写第一个单词的首字符,大写后继单词的首字符。如:removeObject:(id)anObject

● 不要在参数名中使用 pointer 或 ptr,让参数的类型来说明它是指针

● 避免使用 one, two,...,作为参数名

● 避免为节省几个字符而缩写 

按照 Cocoa 惯例,以下关键字与参数联合使用:

NSHighlightRect

NSDeallocateObject

查询属性的函数有个更多的规则要遵循:

● 查询第一个参数的属性的函数,省略动词

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

● 返回 boolean 值的函数,名称使用判断动词 is/does 开头 

const float NSLightGray;

>>> 其他常量

● 通常不使用 #define 来创建常量。如上面所述,整数常量请使用枚举,浮点数常量请使用 const

● 使用大写字母来定义预处理编译宏。如:#ifdef DEBUG

● 编译器定义的宏名首尾都有双下划线。如:__MACH__

● 为 notification 名及 dictionary key 定义字符串常量,从而能够利用编译器的拼写检查,减少书写错误。Cocoa  框架提供了很多这样的范例:

NSColorListIOException

NSColorListNotEditableException

NSDraggingException

NSFontUnavailableException

NSIllegalSelectorException

>>> 通知

如果一个类有委托,那它的大部分通知可能由其委托的委托方法来处理。这些通知的名称应该能够反应其响应的委托方法。比如,当应用程序提交 NSApplicationDidBecomeActiveNotification 通知时,全局 NSApplication 对象的委托会注册从而能够接收 applicaitonDidBecomeActive: 消息。

通知由具有如下形式的全局 NSString 对象标识:

[相关联类的名称] + [Did 或 Will] + [UniquePartOfName] + Notification

例如:

缩写

含义

缩写

含义

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



常见的缩写:

<table xhe-border"="" style="font-family: Arial, Verdana, sans-serif; font-size: 12px; border-top-color: #d3d3d3; border-right-color: #d3d3d3; border-bottom-color: #d3d3d3; border-left-color: #d3d3d3; " cellpadding="0" cellspacing="0" width="398.0">

ASCII,PDF,XML,HTML,URL,RTF,HTTP,TIFF

JPG,GIF,LZW,ROM,RGB,CMYK,MIDI,FTP

> 框架开发者小贴士与技巧

>> Initialize 初始化 

>>> 类初始化

在 initialize 类方法中,能够编写实现一些延迟执行且只被一次的代码,initialize 类方法是由运行时系统在该类响应任何其他消息之前调用的。典型的应用是在其中设置类的版本信息。运行时系统向每个类发送 initialize 消息,即使该类没有实现 initialize,也会调用其基类的某个 initialize 方法。因此一个类的 initialize 方法可能会因为存在继承类的缘故被执行多次。因此有必要使用一定的技巧来防止只执行一次的代码被多次执行。如:NSFoo 类的 initialize 方法实现可能如下:

+ (id) initialize

{

    if (self == [NSFoo class])

    {

        // 初始化代码

    }

    return self;

}
不应当显式调用 initialize 方法。如果你需要激活 initialize 方法,使用 [NSFoo self] 形式的调用。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值