首页 CoCoa编码规则

CoCoa编码规则

举报
开通vip

CoCoa编码规则 介绍 Cocoa 编码指南 使用公共 API 开发 Cocoa 框架、插件及其他可执行文件需要使用的方法和约定不同于应用程序 开发。如果产品主要客户是开发人员,则保证产品的编程接口清晰明确,不至于让开发者产生疑 惑十分重要。这种情况下,API 命名约定就可以派上用场,它可以帮助您保持编程接口一致明确。 另外,框架开发领域也存在一些特定的编程技术—或者说,这些技术对框架开发更加重要—例如 版本管理,二进制兼容性,错误处理以及内存管理等。本节主题包括 Cocoa 命名约定以及我们 提倡的框架编程实践。 本文档的...

CoCoa编码规则
介绍 Cocoa 编码指南 使用公共 API 开发 Cocoa 框架、插件及其他可执行文件需要使用的方法和约定不同于应用程序 开发。如果产品主要客户是开发人员,则保证产品的编程接口清晰明确,不至于让开发者产生疑 惑十分重要。这种情况下,API 命名约定就可以派上用场,它可以帮助您保持编程接口一致明确。 另外,框架开发领域也存在一些特定的编程技术—或者说,这些技术对框架开发更加重要—例如 版本管理,二进制兼容性,错误处理以及内存管理等。本节主 快递公司问题件快递公司问题件货款处理关于圆的周长面积重点题型关于解方程组的题及答案关于南海问题 包括 Cocoa 命名约定以及我们 提倡的框架编程实践。 本文档的组织方式 本主题的文章大致分成两类。第一类数量较多,讲述编程接口的命名约定。苹果公司的 Cocoa 框架使用了这里介绍的命名约定(只有一些小的例外)。该类文章包括如下:  “代码命名基础”  “为方法命名”  “为函数命名”  “为实例变量和数据类型命名”  “可以使用的缩略名称” 第二类的文章(目前只有一篇)讨论了框架编程方面的内容。  “框架开发者可以使用的技巧和技术” 代码命名基础 在面向对象软件库的设计过程中,开发人员经常忽视对类、方法、函数、常量以及其他编程接元 素的命名。本节讨论大多数 Cocoa 接口通用的几条命名约定。 一般性 原则 组织架构调整原则组织架构设计原则组织架构设置原则财政预算编制原则问卷调查设计原则 清晰  最好是既清晰又尽可能地简短,但不要为了追求简短而丧失清晰性: insertObject:atIndex: 好的命名 insert:at: 不清晰;插入什么?“at”表示什么? removeObjectAtIndex: 好的命名 removeObject: 这样命名也不错,因为方法将移除通过参数引用的对象。 remove: 不清晰:要移除什么?  通常情况下,请不要缩写事物的名称,即使名称很长,也应该把它完全拼写出来。 destinationSelection 好的命名 destSel 不清晰 setBackgroundColor: 好的命名 setBkgdColor: 不清晰  您可能觉得某个缩写众所周知,但实际可能并非如此。特别是具有不同文化和语言背景 的开发人员,在遇到您提供的方法或函数的名称缩写时,他们可能不明白其中的含义。  不过,有一些缩写确实很常见并且有很长的使用历史。因此,您可以继续使用。请参看 “可以接受的缩略名称”一节以了解更多的信息。  要防止 API 的名称出现歧义。这里的歧义是指名称具有多种解释方式。 sendPort 该方法是把端口发送出去还是返回发送端口呢? displayName 该方法是显示某个名称还是返回用户界面中接收者的标题呢? 一致性  请尽可能在 Cocoa 编程接口中保持名称一致性。如果不太有把握做到这一点,则请浏览 一下头文件和参考文档中的范例。  如果类方法利用多态,一致性就显得尤其重要。因为在这种情况下,不同类用于完成同 样事件的方法必须具有相同的名称。 - (int)tag 该方法同时定义在 NSView、 NSCell、 NSControl 这三个类里面。 - (void)setStringValue:(NSString 该方法定义于数个 Cocoa 类中 *) 您可以参看 “方法参数”一节。 不能自我指涉  名称不应该自我指涉。 NSString 可以使用 NSStringObject 该名称自我指涉  掩码的常量(可以使用位操作进行组合)不适用这条规则,作为通告的常量也不适用。 NSUnderlineByWordMask NSTableViewColumnDidMoveNotification 前缀 前缀是编程接口名称的重要部分,它们可以区分软件的功能范畴。通常情况下,提供编程接口的 软件会被打包成框架(Foundation 框架以及 Application Kit 框架就是如此)或者是和框架紧密 相关的产品,我们可以利用前缀来区分框架的功能范畴。另外,前缀可以防止第三方开发者定义 的符号和苹果公司定义的符号发生冲突(以及防止苹果公司不同框架之间的符号发生冲突)。  前缀有规定的格式。它需要由两个或者三个大写字符组成,而且不能使用下划线或者“子 前缀”。下面是一些例子: 前缀 Cocoa 的框架 NS Foundation 框架 NS Application Kit 框架 AB Address Book 框架 IB Interface Builder 框架  在为类, 协议 离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载 ,函数,常量以及通过 typedef定义的结构命名时,请使用前缀。但在 命名方法时,请不要使用前缀,因为方法已经存在于其定义类所创建的名称空间中。同理, 在定义结构的字段时,也不要使用前缀。 书写约定 为 API 元素命名的时候, 请遵循下面这几条简单的书写约定:  对于含有多个单词的名称,请不要使用标点符号标志和分割符(下划线,破折号之类); 而是要大写每个单词的首字符并且把这些单词连续地拼写在一起。然而如下这些限定条件 您也需要注意:  方法的名称要以一个小写字符开头,而名称中单词的首字符应该大写。另外, 请不要在方法的名称中使用前缀。 fileExistsAtPath:isDirectory:  如果方法名称的开头是某个众所周知的缩略语,则该原则就不适用。例如 TIFFRepresentation (NSImage),该名称就不遵循该原则。  函数或常量名称使用其关联类的前缀,并且要名称中单词的首字符要大写。 NSRunAlertPanel NSCellDisabled  请不要使用下划线作为前缀来表示私有的属性,尤其是不要在类方法中使用。因为苹果 公司保留使用这种方式,如果第三方再使用,就有可能会导致名称空间冲突。他们有可能 在无意中用自己的方法覆盖了一个已经存在的私有方法,这样做将会带来灾难性的后果。 请参看“私有方法”一节。您可以了解到我们提倡的可供私有API使用的约定。 类和协议的名称 类的名称应包含一个名词,这个名词明确地指示这个类(或者类对象)表示什么或者要做什么。此 外,类名称还应该包含适当的前缀。(请参考“前缀”一节)。Foundation框架以及Application Kit 框架就有很多这样的例子,例如NSString, NSDate,NSScanner,NSApplication,NSButton, 以及NSEvent。 我们应根据协议对方法的分组方式来为其命名:  大部分协议会把一些彼此相关但又不合类关联的方法归结在一起,形成一个特殊的方法 集合。这种协议要合理地命名,不要将其和类名混淆。一种常见的约定是使用动名词格式 (“...ing”): NSLocking 好 NSLock 差(看起来像是个类名)  有一些协议会把一些彼此无关的方法归结在一起(不是创建几个独立的小协议)。对于 这样的协议,我们倾向于把它和一个类联系起来,利用类来作为协议的主要表现。并且, 我们约定让此种协议使用和类一样的名称。 NSObject 协议就是这种情况。它把一些不相关的方法组合在一起,这些方法有的用于查 询任何对象在类层次中的位置,有的可以调用对象的特定方法,有的可以用来增加或者减 少对象的引用计数。由于 NSObject 类提供了这些方法的主要表现,所以我们使用类名作 为协议名称。 头文件 头文件的命名方式很重要,因为通过使用合理的命名约定,您利用文件名称来指示文件中包含的 内容:  声明一个独立的类或协议。.如果一个类或协议不属于某个群,则请将其声明放置在一份 独立的文件,并使用其名称作为文件名。 头文件 声明 NSApplication.h NSApplication 类  声明相关联的类或者协议:如果一群声明(类,类别以及协议)彼此相关,则请将它们 放在一份文件,并使用主要的类或者协议名称作为文件名。 头文件 声明 NSString.h NSString 和 NSMutableString 这两个类 NSLock.h NSLocking 协议以及 NSLock, NSConditionLock,和 NSRecursiveLock 这几个类  包含框架头文件。每个框架都应该包含一份头文件,它的名称和框架名相同,而内容则 包含了框架的全部公共头文件。 头文件 框架 Foundation.h Foundation框架  为另一个框架里的某个类添加 API。如果您在一个框架中声明一些方法,而这些方法属 于另一个框架中某个类的范畴类,则请在原始类的名称后加上“Additions”,然后将其作为 头文件的名称。例如 Application Kit 框架中的 NSBundleAdditions.h头文件就是这种 处理方式。  相关联的函数和数据类型。如果一群函数,常量,结构以及其他数据类型彼此相互关联, 则请将它们放入到合理命名的头文件,例如 NSGaphics.h(位于 Application Kit)。 为方法命名 方法可能是编程接口中最常见的元素了,因此对其命名要特别注意。本部分讨论方法命名的相关 方面: 通用规则 为方法命名时,请记住下面这些通用的指导原则:  方法名称应以小写字符开头,名称中的单词首字符要大写。另外,请不要在方法名称中 使用前缀。您可以参考“书写约定”一节,以了解更多信息。 有两种特定的情况不适用该原则。其一,方法的名称可以使用某个众所周知的缩写开头, 而该缩写可以大写(例如,TIFF 或者PDF)。其二,您可以使用前缀来分组并区分私有 方法(请参考“私有方法”一节)。  如果方法代表一个对象执行的动作,则其名称应该以一个动词开头: - (void)invokeWithTarget:(id)target; - (void)selectTabViewItem:(NSTabViewItem *)tabViewItem  请不要使用 “do”或者 “does”作为名称的一部分,因为这些辅助性的动词 不能为名称增 加更多的含义。同时,请不要在动词之前使用副词或者形容词。  如果方法返回接收者的某个属性,则以属性名称作为方法名。如果方法没有间接地返回 一个或多个值,您也无须使用”get“这样的单词。 - (NSSize)cellSize; 正确 - (NSSize)calcCellSize; 错误 - (NSSize)getCellSize; 错误  您可以参考 “存取方法”一节,以了解更多的信息。  所有参数前面都应使用关键字。 - (void)sendAction:(SEL)aSelector to:(id)anObject forAllCells:(BOOL)flag; 正 确 - (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag; 错 误  参数前面的单词应能够对参数进行描述。 - (id)viewWithTag:(int)aTag; 正确 - (id)taggedView:(int)aTag; 错误  如果您当前创建的方法比起它所继承的方法更有针对性,则您应该在已有的方法名称后 面添加关键字,并将其作为新方法的名称。 - (id)initWithFrame:(NSRect)frameRect; NSView - (id)initWithFrame:(NSRect)frameRect mode:(int)aMode cellClass:(Class)factoryId numberOfRows:(int)rowsHigh numberOfColumns:(int)colsWide; NSMatrix 是 NSView的子 类。  请不要使用”and“来连接两个表示接受者属性的关键字。 - (int)runModalForDirectory:(NSString *)path file:(NSString *) name types:(NSArray *)fileTypes; 正 确 - (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes; 错 误  虽然上面的例子使用”and“这个词感觉还不错,但是随着创建的方法所带有的关键字越来 越多,这种方式会引起问题。  如果方法描述了两个独立的动作,请使用”and“把它们连接起来。 - (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag; NSWorkspace 存取方法 存取方法用于设置或返回对象的属性(也就是对象的实例变量)。由于属性的表示方法不同,我 们提倡的存取方法的格式也有差异:  如果某个属性使用名词来表示,则方法的格式如下: - (void)setNoun:(type)aNoun; - (type)noun; 例如: - (void)setColor:(NSColor *)aColor; - (NSColor *)color;  如果某个属性使用形容词表示, 则方法的格式为: - (void)setAdjective:(BOOL)flag; - (BOOL)isAdjective; 例如: - (void)setEditable:(BOOL)flag; - (BOOL)isEditable;  如果某个属性使用动词表示,则方法的格式为: - (void)setVerbObject:(BOOL)flag; - (BOOL)verbObject; 例如: - (void)setShowsAlpha:(BOOL)flag; - (BOOL)showsAlpha; 这种情况下,动词应使用一般现在时的格式。  请不要使用分词形式把动词转换为形容词: - (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"。这种格式只适 用于需要返回多个数据项的方法。 - (void)getLineDash:(float *)pattern count:(int *)count phase:(float *)phase; NSBezierPath  如果方法格式和上面一样,则其实现应该能够接受 NULL 参数,这样调用者才能够表明 他们对其中的一个或者多个返回值不感兴趣。 委托方法 委托方法是指当某些事件发生时,对象在委托里调用的处理方法(如果委托实现了它们)。委托 方法的格式独特,但它也适用于在对象数据源里调用的方法:  方法名称的开头应标识出发送消息的对象所属的类: - (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row; - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;  在此,类的名称不需要使用前缀并且首字符要小写。  除非方法只有一个参数,并且该参数表示消息的发送者,否则类名称后面都要加上一个 冒号(参数是委托对象的引用)。 - (BOOL)applicationOpenUntitledFile:(NSApplication *)sender;  如果是因为发送了一则通告而导致某个方法被调用,则上述原则不适用。在这种情况下, 方法仅有的一个参数是通告对象。 - (void)windowDidChangeScreen:(NSNotification *)notification;  如果调用某个方法是为了 通知 关于发布提成方案的通知关于xx通知关于成立公司筹建组的通知关于红头文件的使用公开通知关于计发全勤奖的通知 委托某个事件已经发生或者即将发生, 则请在方法名称 中使用“did”或者“will”这样的助动词。 - (void)browserDidScroll:(NSBrowser *)sender; - (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window;  如果调用某个方法是为了 要求 对教师党员的评价套管和固井爆破片与爆破装置仓库管理基本要求三甲医院都需要复审吗 委托代表其他对象执行某件事,当然,您也可以在方法名 称中使用“did”或者“will”,但我们倾向于使用“should”。 - (BOOL)windowShouldClose:(id)sender; 集合方法 对于管理一个对象集合的对象(每个被管理的对象称为集合的一个元素),习惯上,我们要求它 具有如下格式的方法: - (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; 使用集合方法时, 您需要记住下面这两条实现细节:  上述方法通常隐含了它们对于被插入对象的所有权,因此,用于添加或者插入对象的代 码必须增加对象的计数,而用于移除对象的代码也必须要释放对象。  如果被插入的对象需要有一个指针指向其幕后的主对象, 则通常情况下, 您应该使 用 set...这样方法,它可以设置对象的背后对象指针,但并不增加其引用计数。我们 以 insertLayoutManager:atIndex:方法为例,NSLayoutManager 使用如下方法来 实现这一功能: - (void)setTextStorage:(NSTextStorage *)textStorage; - (NSTextStorage *)textStorage;  正常情况下, 您应该不会直接调用 setTextStorage:方法,但可能需要对其进行重 写。 我们还有另外一个示列用于展示集合方法的上述约定,它来自于 NSWindow 类: - (void)addChildWindow:(NSWindow *)childWin ordered:(NSWindowOrderingMode)place; - (void)removeChildWindow:(NSWindow *)childWin; - (NSArray *)childWindows; - (NSWindow *)parentWindow; - (void)setParentWindow:(NSWindow *)window; 方法的参数 下面是数条和方法参数命名相关的通用规则:  和方法名称一样, 参数的名称也是以小写的字符开头,并且后续单词的首字符要大写。 例如: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 框架类设计子类时,您无法知道您的某个私有方法 是否在无意中覆盖了具有相同名称的私有的框架方法。 大部分 Cocoa 框架中私有方法的名称都带有一个下划线前缀(例如,_fooData ),这个前缀 把方法标记为私有。根据这样的实际情况,我们给出两条建议:  请不要在您的私有方法中使用下划线作为前缀,因为苹果公司保留使用这种命名约定。  在为某个很大的 Cocoa 框架类(例如 NSView)派生子类时,如果需要绝对保证子类私 有方法名称不会和超类发生冲突,则您可以为子类私有方法添加自己的前缀。前缀应该尽 可能地具有唯一性,也许您的前缀可以基于公司或者项目名称,并且使用"XX_"这样的格 式。例如,如果您的项目叫做 Byte Flogger,则前缀可以是 BF_addObject:这样的格式。 尽管为私有方法名称添加前缀似乎和早前我们对类方法的命名要求相矛盾,但这是因为此处的目 的和早前不同:我们这么做是为了避免在无意中重写了超类中的私有方法。 为函数命名 Objective-C 允许使用函数或者方法来表达行为。如果底层对象总为单例或者处理的事物明显是 功能性子系统,则您应该使用函数而非类方法。 请遵守下述几条函数通用命名规则:  函数名称和方法名称格式相似,但是有两种情况例外:  函数要使用前缀开头,并且这个前缀和类或者常量所使用的一样。  前缀后面的单词首字符要大写。  大多数函数名称以动词开头,该动词描述了函数的作用: NSHighlightRect NSDeallocateObject 用于查询属性的函数有一套更细致的命名规则:  如果函数返回其首个参数的某个属性,则请省略掉函数名称中的动词。 unsigned int NSEventMaskFromType(NSEventType type) float NSHeight(NSRect aRect)  如果函数返回的值是个引用,则请在函数名称中使用“Get”。 const char *NSGetSizeAndAlignment(const char *typePtr, unsigned int *sizep, unsigned int *alignp)  如果函数返回值是布尔类型,则它应以曲折动词开头。 BOOL NSDecimalIsNotANumber(const NSDecimal *decimal) 为实例变量和数据类型命名 本节描述实例变量、常量、异常、以及通知的命名约定。 实例变量 在为某个类添加实例变量时,请记住下面几个因素:  避免创建公共实例变量。开发人员应该关心对象的接口,而不是对象的数据存储方式这 样的细节。  请把实例变量显式声明为@private或者@protected。如果您预期所提供的类会被子类 化,并且子类可能需要父类的数据, 则请使用@protected指令来修饰实例变量。  请确保实例变量的名称能够扼要地描述它所保存的属性。 如果实例变量将作为类对象的可访问属性,则请务必为其编写存取方法。 常量 根据常量创建方式不同,其命名规则也有所差异。 枚举常量  请使用枚举类型来表示一群相互关联的整数值常量。  枚举常量及其所属的通过typedef定义的数据类型遵循和函数一样的命名约定(请查看 “为函数命名”一节)。下面是一个取自NSMatrix.h文件的例子 typedef enum _NSMatrixMode { NSRadioModeMatrix = 0, NSHighlightModeMatrix = 1, NSListModeMatrix = 2, NSTrackModeMatrix = 3 } NSMatrixMode;  请注意,在上述例子中,typedef标签不是一定要具有的。  您也可以创建匿名的枚举类型来表示诸如位掩码这样的事物。例如: enum { NSBorderlessWindowMask = 0, NSTitledWindowMask = 1 << 0, NSClosableWindowMask = 1 << 1, NSMiniaturizableWindowMask = 1 << 2, NSResizableWindowMask = 1 << 3 }; 使用 const 创建的常量  请使用 const 来创建浮点值常量。如果某个整数值常量和其他的常量不相关,您也可以 使用 const 来创建,否则,则应使用枚举类型。  下面的声明展示了 const常量的格式: const float NSLightGray;  使用枚举类型声明的常量遵循和函数相同的命名约定。(请参考“为函数命名”一节)。 其他类型的常量  通常情况下, 请不要使用#define预处器理命令创建常量。对于整数值常量,请使用 枚举类型创建,而对于浮点值常量,请使用 const修饰符创建,这和前述的原则一样。  有些符号,预处理器需要对其进行计算,以便决定是否要对某一代码块进行处理,则它 们应该使用大写字符表示。例如: #ifdef DEBUG  请注意,编译器定义的宏,其开头和结尾要具有两个下划线字符。例如: __MACH__  对于通告名称或字典关键字的字符串,请将其定义为常量。通过使用字符串常量,编译 器可以验证字符串是否被正确赋值(也就是说, 编译器将执行拼写检查)。Cocoa 框架 提供很多字符串常量的例子,例如: APPKIT_EXTERN NSString *NSPrintCopies;  在实现文件中,NSString 的实际值被指定为常量。(请注意,APPKIT_EXTERN宏经过 计算之后是 Objective-C 中的 extern关键字)。 异常和通告 异常和通告的名称遵循相似的命名规则,但是我们为二者推荐的使用模式并不相同。 异常 尽管您可以随意地将异常(即 NSException 类和一些相关联的函数所提供的机制)用于任何目 的,但是通常情况下,cocoa 不会利用他们来处理常规的、可预期的错误条件。这类错误应使用 诸如 nil、 NULL、 NO这样的返回值或者错误码来表示。通常,Cocoa 把异常用于表示诸如数 组索引越界这样的编程错误。 异常使用全局的 NSString 对象来标识,其名称按如下的方式进行组合: [Prefix] + [UniquePartOfName] + Exception 异常名称中的具有唯一性的那部分,其组成词应该拼写在一起, 并且每个单词的首字符要大写。 下面是一些例子: NSColorListIOException NSColorListNotEditableException NSDraggingException NSFontUnavailableException NSIllegalSelectorException 通告 如果某个类含有委托,则通过所定义的委托方法,类的委托可以收到大部分通告。通告的名称应 该反映相应的委托方法。例如,一旦应用程序发送一则 NSApplicationDidBecomeActiveNotification的通告,则全局 NSApplication 对象的委托就 会自动进行注册,这样它就可以接收到一条 applicationDidBecomeActive:的消息。 通告使用全局的 NSString 对象进行标识,其名称按如下的方式组合: [Name of associated class] + [Did | Will] + [UniquePartOfName] + Notification 例如: NSApplicationDidBecomeActiveNotification NSWindowDidMiniaturizeNotification NSTextViewDidChangeSelectionNotification NSColorPanelColorDidChangeNotification 可以使用的缩略名称 设计编程接口时,通常不应使用名称缩写(请参考 “通用规则”一节)。但是下列缩写可以继续用, 因为它们要么已得到广泛认可,要么从过去就开始使用了。另外,请注意下面两件事情,它们也 跟名称缩写有关:  标准 C 库里已使用很长时间的缩写格式—例如,“alloc”和“getc”—可以复制到 Cocoa 中。  参数名称可以更加随意地使用缩写(例如,“imageRep”、 “col” (表示“column”)、“obj”、 以及“otherWin”)。 缩写 意义和注释 alloc 分配内存 alt 可选的 app 应用程序。例如,NSApp 表示全局的应用程序对象。但是在委托方法中,需要把 “application”整个拼写出来。 calc 计算 dealloc 释放内存 func 函数 horiz 水平的 info 信息 init 初始化(表示初始化新对象的方法) int 整数 max 最大值 min 最小值 msg 消息 nib Interface Buidler 档案 pboard 粘贴板(只能粘贴常量) rect 矩形 Rep 表现形式(用于诸如 NSBitmapImageRep 这样的类) temp 暂时性 vert 垂直 您可以用计算机行业中很常见的缩略语来代替其所表示的单词。下面是一些知名度比较高的简 写: ASCII PDF XML HTML URL RTF HTTP TIFF JPG GIF LZW ROM RGB CMYK MIDI FTP 框架开发者可以使用的技巧和技术 相对于其他的开发者而言,框架开发者要更加注意编写代码的方式。因为许多客户应用程序可能 链接到框架,而这样宽泛地暴露接口,就导致框架的任何缺点都可能通过系统放大。下面的条款 讨论一些框架编程技术,框架开发者可以利用它们来确保框架的高效性和完整性。 请注意:此处所讨论的一些技术并不局限于框架开发。将之用于应用程序开发同样卓有成效。 初始化 下述意见和建议涵盖框架初始化方面的内容。 类的初始化 initialize类方法中的代码只执行一次,它是类里面第一个被调用的方法。我们通常利用该方 法来设置类的版本号(请参考“版本化和兼容性”一节)。 对于继承链中的每一个类,不论其是否实现 initialize方法,运行时都会向它发送 initialize 消息。这可能导致一个类的 initialize方法被多次调用(举个例子,如果子类没有实现 initialize方法,则其父类的方法将被调用两次)。但通常您希望始化代码仅执行一次,为确保 如此,您可以执行如下检查: if (self == [NSFoo class]) { // the initializing code } 您不应该显式地调用 initialize方法。如果需要触发初始化行为,则请调用一些无害的方法, 例如: [NSImage self]; 指定初始化函数 指定初始化函数是类的一个 init方法,它调用超类的某个 init方法(其他的初始化函数调用 类自己定义的 init方法)。每个公共类都应包含一个或多个指定初始化函数。举些例子,NSView 的 initWithFrame:方法以及 NSResponder 的 init方法都是指定初始化函数。在某些情况下, 类的 init方法并不想被重载,比如 NSString 和其他面向类簇的抽象类,因而其子类应该实现 自己的初始化方法。 您应该明确标示出指定初始化函数,因为该信息对于想根据您的类来派生子类的开发者有重要的 意义。一个子类可以只重载指定初始化函数,这对其他所有初始化函数没有影响,它们仍将按其 原先设计的行为工作。 在实现一个框架类时,您经常需要为其实现诸如 initWithCoder:以及 encodeWithCoder:这样 的归档方法。请注意,对象解档时未发生的事情不要放在初始化代码路径里执行。对于实现归档 功能的类,我们有一个比较好的方法可以做到这一点,那就是在类的指定初始化方法以及 initWithCoder: 方法(该方法也是个指定初始化函数)中调用一个公共的例程。 初始化过程中的错误检测 为确保能够恰当地检测并传播错误,一个设计良好的初始化方法应完成如下步骤: 1. 调用 super的 init方法对 self 重新赋值。 2. 检测指定初始化方法的返回值是否为 nil。返回值为 nil表明超类的初始化过程出现错 误。 3. 如果当前类在初始化的过程中出现错误,则请释放对象并且返回 nil值。 列表 1 描述的方法可以完成上述步骤。 列表 1 初始化过程中的错误检测 - (id)init { if ((self = [super init]) != nil) { // call a designated initializer here // initialize object ... if (someError) { [self release]; // [self dealloc] or [super dealloc] might be self = nil; // better if object is malformed } } return self; } 版本化和兼容性 在向框架添加新类或新方法时,您通常没必要为每个新功能群指定新的版本号。因为一般情况下, 开发者会执行(或者说,应该执行)诸如 respondsToSelector:这种 Objective-C 的运行时检 测来判断给定的系统是否存在某种功能。开发者比较喜欢使用这种方式来检测新功能,同时它也 是最动态的方式。 不论如何,您可以使用数种技术以确保新版本的框架能被正确标志并尽可能地兼容早期版本。 框架的版本 如果已存在的新功能或者错误改正不容易通过运行时进行检测,则您应该为开发者提供检测这些 变更的办法。有一种办法是把确切的框架版本号保存起来,然后让该号码对开发者可见:  把变更归档在一个版本号下面(例如,归档在发布记录中)。  设置框架的当前版本号并且提供某种方法使之全局可见。您可以把版本号保存在框架的 信息属性列表(Info.plist),这样就可以从该列表获取版本号。 基于键的归档 如果框架对象需要被写入到 nib 文件,则它们必须能够自我归挡 。另外,如果文档使用归挡机 制来保存文档数据,则您也要对它们做归挡。在归挡时,您可以使用“老风格”(利用 initWithCoder:和 encodeWithCoder:这样的方法)。但是,为了更好地兼容过去、现在、以 及未来的框架版本,您应该基于健进行归档。 基于键进行归档,对象就可以使用键来读取或写入被归挡值。相对以往的归挡机制,该方法可以 在前向和后向兼容性上提供更多的灵活性。因为老归档机制要 求代码和读取或写入的值维持相 同的顺序,而且它也没有什么好办法来改变已写到档案的数据。如果您需要了解更多基于键的归 档机制,请参考 Cocoa归档和序列化编程指南 (Archives and Serializations Programming Guide for Cocoa)一文。 对于正在编写的新的类,请为其使用基于键的归档机制。如果之前已发布的类使用了老归档机制, 您也无需再采取任何措施。如果对象实现了 Mac OS X 10.2 版本之前的归档机制,则它必须能 从档案中读取内容并能其内容写入到档案。但如果您在 Mac OS X v10.2 及之后的平台上为该对 象添加新属性,则您不必,实际上是不应该,将这些属性保存到老档案中(这样做可能会使老档 案在更早的系统中变得不可读 取),这种情况下,新属性应使用键值归档机制。 请注意下列和基于键归档相关的事实:  如果档案中的某个键丢失,则在获取这个键对应值的时候,依据所要求的类型,其返回 值可能是 nil、 NULL、NO、0、或者 0。通过对该返回值进行测试,您可以减少写到档案 中的数据。同时,还可以检测某个键是否已被写入到档案中。  如果使用旧式归档,则 initWithCoder:的 实现需要独自挑起兼容性的重担。但如果使 用键值归档,则归档方法和解档方法都可以采取一些措施以保证兼容性。举个例子,一个 新版本的类的归档方法可能使用 键来写入一个新值,而依旧把早期的字段写入到档案中, 这样类的旧版本仍然可以理解该对象。与此同时,我们还可以在解档方法中使用某种合理 的方式以处理数值 缺失的情况,从而为将来的版本保留一些灵活性。  在命名框架类的档案键时,我们提倡使用和框架其他 API 元素一样的前缀,前缀后面再 使用实例变量名称。您只要确保它的名称不会和任意的子类或者超类名称发生冲突即可。  如 果您使用一个工具函数向档案中写入一个基本数据类型(换句话说,就是一个非对 象的值),则请务必为该数值使用一个唯一键。举个例子,如果您有一个对矩形归 档的 “archiveRect” 例程,则您应该为该函数传入一个键作为参数。您可以直接把它作为档案键; 或者,如果这个例程向档案写入多个值(例如,写入四个浮点数值),则它应该把每个 数 值自身独有的位添加到所提供的键上面。  位字段对于编译器和比特序有依赖关系,按照位字段现有的格式进行归档可能会有危 险。只有当有多个位元需要被写入档案多次时,我们才会对位字段进行归档,这主要是为 了提高性能。请参看 “位字段”一节 以获取相关的建议。 对象的尺寸和保留字段 每个 Objective-C 的对象都有一个尺寸,它由对象自身实例变量加上对象所有超类具有的实例变 量得到的总尺寸决定。如果改变了一个类的尺寸, 则其拥有实例变量的子类必须重新编译。为 了保持二进制兼容性,通常情况下,我们不能通过向类添加新的实例变量或者去除类里面不必要 的实例变量来改变对象的 尺寸。 因此,对于新的类,为其留下几个额外的”保留“字段以便于将来扩展是个不错的想法。如果一个 类只会有少数的几个实例,这个想法显然不成问题。但如果这个类会被实例化数千次,则您可能 需要让保留的单个变量的尺寸小一些(也就是说,任意对象都占用四个字节)。 对于较早的类的对象,如果它们的空间已经用完(并且假定实例变量没有被导出成为公共变量), 则您可以移动实例变量,或者把它们捆绑在一起,使之成为 一个更小的字段。通过对实例变量进 行重新排布,您就有可能添加新的数据而不会导致对象的总尺寸发生改变。或者您可以把一个剩 余的保留槽作为指针,使它可以 指向一块额外的内存,然后您在对象初始化的时候分配这块内 存(并且在对象释放的时候销毁它)。又或者您可以把额外的数据放入到一张外部的哈希表(例 如放入 NSDictionary);这种方法对于那些很少创建使用的实例变量具有很好的效果。 异常和错误 大多数 Cocoa 框架的方法不会强制要求开发者捕捉处理异常,因为程序正常执行时不会产生异 常,而且我们通常也不使用异常来表示可预期的运行时错误或用户错误。下面这些例子属于可预 期的运行时错误或者用户错误:  文件找不到  用户不存在  试图打开应用程序中一个错误类型的文档  把字符串转化为特定编码时出现错误 但是不管怎么样, Cocoa 确实会引发异常以指示下面这些编程错误或者逻辑错误:  数组索引越界  试图改变一个不可改变的对象  错误参数类型 我们认为应用程序推向市场之前,开发者会对其进行测试,发现并解决这些类型的错误。因此, 应用程序不需要在运行时处理上述异常。如果出现一个异常发 生但应用程序没有捕捉,则最顶 层的缺省处理器通常会捕捉并且报告该异常,然后程序将继续执行。开发者可以选择替换掉这个 缺省的异常处理器,新的处理器可以 更详细地描述什么地方发生了错误,并且还能够让用户选 择是否保存数据并且推出应用程序。 错误是 Cocoa 框架不同于其他软件库的又一个地方。Cocoa 的方法通常不返回错误码。某些情 况下,一个错误具有一个合理或者可能的原因,方法通过对一个布尔值或者对象返回值 (nil/non-nil)进行简单测试以判断该情况;但是返回 NO或者 nil值的原因则被记录在文档 中。另外,您不应该使用错误码来指示需要在运行时处理的编程错误,相反您应该引发一个异常, 或者在某些情况下,您也可以只记录下该错误而不引发异常。 举个例子,NSDictionary 的 objectForKey:方法会返回所找到的对象,如果对象找不到,则它 会返回 nil值。NSArray 的 objectAtIndex:法不可能返回 nil值(除非我们把通用的编程语言 约定重载成向 nil对象发送消息都会返回 nil值),因为 NSArray 对象不能保存 nil值,并且 所有的越界访问都被定义成编程错误,这种错误引发异常而并不返回 nil对象。如果对象不能 使用用户提供的参数进行初始化,许多 init方法都会返回 nil值 在少数情况下,一个方法需要多个不同的错误码是合理的。这时,该方法需要将错误码指定到一 个传引用参数,然后您可以利用该参数返回一个错误码,也可 以返回一个本地化的错误字符串, 或者一些其他的可以描述错误的信息。举个例子,您可以把错误转换成 NSError 对象返回(请 参看 Foundation 框 架的 NSError.h头文件以获取更多的细节)。而除了这个 NSError 对象, 方法还能直接返回相对简单的 BOOL值或者 nil值。另外要注意,这种方法的所有传引用参数都 是可选的。因此,如果发送者不想了解错误原因,它们可以传一个 NULL 值给错误码参数。 重要: NSError 类在 Mac OS X v10.3 之后的版本对外公开。 框架数据 框架数据的处理方式可能会对性能、跨平台兼容性、以及其他某些方面产生影响。本节讨论一些 和框架数据相关的技术。 常量数据 出于性能的原因,您应尽可能多地把框架数据标志为常量,因为这样可以减小 Mach-O 二进制 文件的__DATA 段的尺寸。没有 const标记的全局或静态的数据最终会存放在__DATA段的 __DATA节。对于每一个使用该框架的应用程序实例,这种类型的数据都会占用内存。尽管多出 500 字节(举个例子)好像没那么糟糕,但是这有可能导致应用程序所需的内存页面的数量增多 —即每个应用程序都需要额外的四千字节的内存。 您应该为所有不变的数据添加 const标记。具有 const标记的数据块,如果其中没有 char * 类型的指针,则该数据会被存放在__TEXT段中(这会使数据成为真正的常量); 否则数据就会 被存放在__DATA段中,但是这些数据不可以被写入(除非预绑定未完成,如果预邦定已经完成, 则只能在加载的时候,通过移动二进制文件的方式来写入)。 您应该初始化静态变量,这样可以确保该变量被合并到__DATA段的__data节中而非__bss节。 如果没有明显的值用于初始化静态变量,则请使用 0、NULL、0.0、或者任何恰当的值。 位字段 如果使用有符号的值来表示位字段,而代码又假定这个位字段是布尔值,则可能会导致未定义的 行为。只有一个位的位字段尤为如此。因为在这种情况下,这 个位字段只能存储 0 和 -1(取决 于编译器的实现),把它和 1 做比较,其结果总是不相等。因此,只有一个位的位字段应该是 无符号的。举个例子,如果您在代码中遇到如下情况: BOOL isAttachment:1; int startTracking:1; 您应该把上述代码中的类型改为 unsigned int 和位字段相关的另一个问题是归档。通常情况下,您不应该按照当前格式将其写入到磁盘或者档 案中,因为当
本文档为【CoCoa编码规则】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_252386
暂无简介~
格式:pdf
大小:252KB
软件:PDF阅读器
页数:26
分类:互联网
上传时间:2011-08-31
浏览量:26