编程约定 – Objective-C编程快速入门教程

上一章Objective-C编程快速入门教程请查看:处理错误?
当你使用框架类时,你会注意到Objective-C代码非常容易阅读。类和方法的名称比一般C代码函数或C标准库的名称更具描述性,驼峰大小写用于多个单词的名称。当你编写自己的类时,你应该遵循Cocoa和Cocoa Touch使用的相同约定,以使你的代码更具可读性,对你和其他可能需要使用你的项目的Objective-C开发人员来说都是如此,并保持代码库的一致性。
此外,许多Objective-C和框架特性要求你遵循严格的命名约定,以便各种机制能够正确工作。例如,访问器方法名必须遵循约定,以便使用诸如键值编码(KVC)或键值观察(KVO)之类的技术。
本章介绍了Cocoa和Cocoa Touch代码中使用的一些最常见的约定,并解释了在整个应用程序项目(包括其链接框架)中名称必须是唯一的情况。
有些名字在你的应用程序中必须是唯一的每次创建新类型、符号或标识符时,应首先考虑名称必须惟一的范围。有时这个范围可能是整个应用程序,包括它的链接框架; 有时范围仅局限于一个封闭的类,甚至只是一个代码块。
类名在整个应用程序中必须是唯一的
Objective-C类的命名必须是唯一的,不仅要在项目中编写的代码中如此,还要在任何框架或包中都是如此。举个例子,你应该避免使用通用的类名,比如ViewController或TextParser,因为你在应用程序中包含的框架可能不遵守约定,创建的类名也不相同。
为了保持类名的唯一性,惯例是在所有类上使用前缀。你会注意到Cocoa和Cocoa Touch类名通常以NS或UI开头。像这样的两个字母前缀是Apple保留给框架类使用的。当你了解更多关于Cocoa和Cocoa Touch的知识时,你会遇到许多与特定框架相关的前缀:

前缀框架
NSFoundation (OS X and iOS) 和 Application Kit (OS X)
UIUIKit (iOS)
ABAddress Book
CACore Animation
CICore Image
你自己的类应该使用三个字母前缀。这些可能与你的公司名称和你的应用程序的名字,甚至在应用程序特定的组件。作为一个例子,如果你的公司被称为低语橡树,和你是开发一个游戏叫斑马惊讶的是,你可能会选择wz或沃兹作为类前缀。
你还应该用一个名词来命名你的类,让它清楚地表示类的含义,比如Cocoa和Cocoa Touch中的这些例子:
  • NSWindow
  • CAAnimation
  • NSWindowController
  • NSManagedObjectContext
如果一个类名中需要多个单词,则应该使用驼峰大小写,将每个后续单词的第一个字母大写。
方法名在类中应该是表达性的和惟一的
一旦为类选择了惟一的名称,则声明的方法只需在该类中是惟一的。例如,通常在另一个类中使用与方法相同的名称来覆盖超类方法,或者利用多态性。在多个类中执行相同任务的方法应该具有相同的名称、返回类型和参数类型。
方法名没有前缀,应该以小写字母开头; 驼峰大小写再次用于多个单词,例如以下来自NSString类的例子:
  • length
  • characterAtIndex:
  • lengthOfBytesUsingEncoding:
如果一个方法有一个或多个参数,方法的名称应该表明每个参数:
  • substringFromIndex:
  • writeToURL:atomically:encoding:error:
  • enumerateSubstringsInRange:options:usingBlock:
方法名的第一部分应该指示调用方法的主要意图或结果。例如,如果一个方法返回一个值,第一个单词通常表示将要返回的内容,比如长度、字符……和子串……上面所示的方法。如果需要指示关于返回值的重要信息,比如mutableCopy、capitalizedString或NSString类中的lastPathComponent方法,就会使用多个单词。如果一个方法执行一个操作,例如写入磁盘或枚举内容,第一个单词应该表示该操作,如write…和列举……方法。
如果一个方法包含一个发生错误时要设置的错误指针参数,这应该是该方法的最后一个参数。如果一个方法接受一个块,那么块参数应该是最后一个参数,以便在内联指定一个块时使任何方法调用尽可能可读。出于同样的原因,最好尽可能避免接受多个块参数的方法。
同样重要的是,要力求方法名称清晰而简洁。清晰并不一定意味着冗长,但简洁并不一定导致清晰,所以最好是找个折中的办法:
stringAfterFindingAndReplacingAllOccurrencesOfThisString:withThisString:太详细
strReplacingStr:str:太简洁
stringByReplacingOccurrencesOfString:withString:刚刚好
你应该避免在方法名称中使用缩写词,除非你确定缩写词在多种语言和文化中都是众所周知的。常见缩写的列表以可接受的缩写和首字母缩写形式给出。
在框架类的类别中,总是对方法名使用前缀
使用类别向现有框架类添加方法时,应在方法名称上包含前缀以避免冲突,如“避免类别方法名称冲突”中所述。
局部变量在同一范围内必须是唯一的
因为Objective-C是C语言的超集,所以C变量范围规则也适用于Objective-C。局部变量名不得与同一作用域内声明的其他变量冲突:
- (void)someMethod { int interestingNumber = 42; ... int interestingNumber = 44; // not allowed }

虽然C语言允许你声明一个新的局部变量,它的名字和在封闭范围内声明的一样,就像这样:
- (void)someMethod { int interestingNumber = 42; ... for (NSNumber *eachNumber in array) { int interestingNumber = [eachNumber intValue]; // not advisable ... } }

它使代码混乱,可读性较差,所以最好尽可能避免这种情况。
一些方法名必须遵循约定除了考虑唯一性之外,一些重要的方法类型必须遵循严格的约定。除了Cocoa和Cocoa Touch中的类需要的行为之外,Objective-C、编译器和运行时的一些底层机制也使用这些约定。
访问器方法名必须遵循约定
当你使用@property语法声明对象的属性时(如封装数据中所述),编译器将自动合成相关的getter和setter方法(除非另有指示)。如果出于任何原因需要提供自己的访问器方法实现,那么务必确保为属性使用正确的方法名,以便通过点语法调用方法。
除非另外指定,否则getter方法应该使用与属性相同的名称。对于名为firstName的属性,访问器方法也应该被称为firstName。这个规则的例外是布尔属性,getter方法应该以is开头。例如,对于一个名为pause的属性,应该调用getter方法ispause。
属性的setter方法应该使用形式setPropertyName:。对于一个名为firstName的属性,setter方法应该被称为setFirstName:; 对于一个名为的布尔属性,应该调用setter方法set:。
虽然@property语法允许你指定不同的访问器方法名,但是你应该只在布尔属性之类的情况下这样做。必须遵循这里描述的约定,否则像键值编码这样的技术(使用valueForKey:和setValue:forKey:获取或设置属性的能力)将不起作用。有关KVC的更多信息,请参见键值编码编程指南。
对象创建方法名称必须遵循约定
正如在前面几章中看到的,通常有多种方法来创建类的实例。你可以使用分配和初始化的组合,就像这样:
NSMutableArray *array = [[NSMutableArray alloc] init];

或者使用新的便利方法来替代显式调用alloc和init:
NSMutableArray *array = [NSMutableArray new];

一些类还提供了类工厂方法:
NSMutableArray *array = [NSMutableArray array];

类工厂方法应该总是以它们所创建的类的名称(不带前缀)开头,只有具有现有工厂方法的类的子类例外。例如,对于NSArray类,工厂方法以数组开始。NSMutableArray类没有定义任何自己的类特定的工厂方法,所以可变数组的工厂方法仍然以array开头。
【编程约定 – Objective-C编程快速入门教程】有各种各样的内存管理规则支持Objective-C,编译器使用这些规则来确保对象在需要的时候保持活动状态。虽然你通常不需要太担心这些规则,但是编译器会根据创建方法的名称来判断应该遵循哪些规则。通过工厂方法创建的对象与通过传统分配和初始化创建的对象或通过使用autorelease池块创建的对象稍有不同。有关自动释放池块和内存管理的更多信息,请参阅高级内存管理编程指南。

    推荐阅读