那天是你用一块红布
蒙住我双眼也蒙住了天
你问我看见了什么
我说我看见了幸福
--------崔健《一块红布》
今天继续苹果编码规范。 原文地址:https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html#//apple_ref/doc/uid/20001282-BCIGIJJF
方法命名
方法或许是编程中最常用的元素了,所有你要特别注意如何给它们命名。本节讨论方法命名的以下几个方面:
通用规则
当给方法命名时,需要记住以下几个通用指导:
1首字母小写,之后嵌入的单词首字母大写。不要使用前缀。
这条规则有两个例外。你可以使用一些众所周知的大写缩写单词来作为方法名字的开头(比如TIFF和PDF)。你可以使用前缀来命名私有方法。
2对于那些要标示一个对象的动作的方法,以动词开头:
- (void)invokeWithTarget:(id)target;
- (void)selectTabViewItem:(NSTabViewItem *)tabViewItem
不要使用“do"或“dose”作为名字的一部分,因为这种辅助的动词没什么意义。同样,不要在动词前加副词和形容词。
3如果该方法返回接受者的属性,以该属性来命名方法。不需要使用“get”,除非间接地返回一个或多个值。(其他语言似乎喜欢用get)
- (NSSize)cellSize; 正确
- (NSSize)calcCellSize; 错误
- (NSSize)getCellSize; 错误
4在各个参数前加上关键字。
- (void)sendAction:(SEL)aSelector toObject:(id)anObject forAllCells:(BOOL)flag; 正确
- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag; 错误
5参数前的单词应该对该参数进行说明解释。(就是解释该参数是干嘛的)
- (id)viewWithTag:(NSInteger)aTag; 正确
- (id)taggedView:(int)aTag; 错误
6当你创造一个比被继承的方法还要具体的方法时,要在其后添加新的关键字(进行解释说明)。
- (id)initWithFrame:(CGRect)frameRect; NSView,UIView.
- (id)initWithFrame:(NSRect)frameRect mode:(int)aMode cellClass:(Class)factoryId
numberOfRows:(int)rowsHigh numberOfColumns:(int)colsWide; NSMatrix, NSView的子类
7不要用“and”来连接接收者的属性的关键字。(看来之前我都做错了。。。。)
- (int)runModalForDirectory:(NSString *)path file:(NSString *) name types:(NSArray *)fileTypes; 正确
- (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes; 错误
也许“and”在这个例子中看起来不错,但是,当你添加越来越多的关键字时,它就会造成问题。
8如果一个方法描述了两个行为,使用“and”来连接它们。
- (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag; NSWorkspace.
存取方法
获取方法,指的是设置和返回一个对象的一个属性的值的方法。它们有特定的推荐格式,取决于属性的类别。
1如果属性是名词,格式是:
- (type)noun;
- (void)setNoun:(type)aNoun;
比如:
- (NSString *)title;
- (void)setTitle:(NSString *)aTitle;
2如果属性是形容词,格式是:
- (BOOL)isAdjective;
- (void)setAdjective:(BOOL)flag;
比如:
- (BOOL)isEditable;
- (void)setEditable:(BOOL)flag;
3如果属性是动词,格式是:
- (BOOL)verbObject;
- (void)setVerbObject:(BOOL)flag;
比如:
- (BOOL)showsAlpha;
- (void)setShowsAlpha:(BOOL)flag;
动词应该是一般现在时。
4不要使用分词来把动词变成形容词。
- (void)setAcceptsGlyphInfo:(BOOL)flag; 正确
- (BOOL)acceptsGlyphInfo; 正确
- (void)setGlyphInfoAccepted:(BOOL)flag; 错误
- (BOOL)glyphInfoAccepted; 错误
5你可以使用一些情态动词(比如can,should,will等)来说明方法的含义,但不要使用“do”和
“does”
- (void)setCanHide:(BOOL)flag; 正确
- (BOOL)canHide; 正确
- (void)setShouldCloseDocument:(BOOL)flag; 正确
- (BOOL)shouldCloseDocument; 正确
- (void)setDoesAcceptGlyphInfo:(BOOL)flag; 错误
- (BOOL)doesAcceptGlyphInfo; 错误
6仅仅在间接返回对象和值的情况下使用“get”。仅在需要返回多个项的时候,才使用这种格式。
- (void)getLineDash:(float *)pattern count:(int *)count phase:(float *)phase; NSBezierPath.
在这些方法中,方法的实现应该可以接收参数的值为null,因为方法的调用者未必对它们的值感兴趣。
代理方法
1以发送该消息的对象所属的类作为方法的开头。
- (BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(int)row;
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
类名省略前缀,并且首字母小写。
2类名之后加冒号(参数为触发该代理的对象),除非该方法只有一个参数:发送者
- (BOOL)applicationOpenUntitledFile:(NSApplication *)sender;
3一个例外是,被抛出的作为通知结果的那些方法。那个唯一的参数就是通知对象。
- (void)windowDidChangeScreen:(NSNotification *)notification;
4使用did,will来表示已经发生或将要发生。
- (void)browserDidScroll:(NSBrowser *)sender;
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window;
5也可以使用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;
1如果集合是无序的,返回一个NSSet而不是NSArray。
2如果要将元素插入到特定的位置,使用下面的格式:
- (void)insertLayoutManager:(NSLayoutManager *)obj atIndex:(int)index;
- (void)removeLayoutManagerAtIndex:(int)index;
一些实现细节需要牢记:
1这些方法通常都隐含着被插入的对象,所以对他们的add 和insert的操作应该retain它们,而remove操作需要release它们。
2If the inserted objects need to have a pointer back to the main object, you do this (typically) with aset...method that sets the back pointer but does not retain. In the case of theinsertLayoutManager:atIndex:method, the NSLayoutManager class does this in these methods:
- (void)setTextStorage:(NSTextStorage *)textStorage;
- (NSTextStorage *)textStorage;
You would normally not callsetTextStorage:directly, but might want tooverrideit.(这一段不知道啥意思。。。。)
以下是NSWindow的一些方法作为例子:
- (void)addChildWindow:(NSWindow *)childWin ordered:(NSWindowOrderingMode)place;
- (void)removeChildWindow:(NSWindow *)childWin;
- (NSArray *)childWindows;
- (NSWindow *)parentWindow;
- (void)setParentWindow:(NSWindow *)window;
方法参数
1参数的首字母小写,之后的单词首字母大写:removeObject:(id)anObject。
2名字中不要使用“pointer”或者“ptr”。让参数的类型而不是名字来表明它是不是一个pointer。
3参数名字避免使用只有一个或两个字母的名字。
4不要使用简写。
在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框架的子类时,你无法知道你的私有方法是否无意之中override了私有框架的方法。
Cocoa框架的私有方法通常都有一个下划线前缀,比如:_fooData,以此表明它们是私有方法,因此,请遵循下面两个建议:
1不要使用下划线字符作为你的私有方法的前缀。苹果公司保留这项权利。
2如果你要写一些大的类(比如NSView或UIView)的子类,你必须绝对肯定你的私有方法和父类的私有方法的名字绝不相同。你可以给你的私有方法添加自己的前缀,该前缀尽可能地独一无二。可能以你的公司或者项目作为前缀,并且遵循“xx_"的格式。比如你的项目叫Byte Flogger,那你的前缀可以是BF_addObject:
虽然给私有方法加前缀的建议看上去与前面说的方法存在于该类的命名空间的说法有矛盾,但是这里的目的是不同的:给私有方法加前缀是为了防止无意之中override父类的私有方法。
网友评论