还剩23页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
O__ective-C编程规范目录例子空格与格式o空格与制表符o行宽o方法声明与定义o方法调用o@public与@privateo异常o协议命名o文件名oO__ective-C++o类名o分类名oO__ective-C方法名o变量名注释o文件注释o声明注释o实现注释o对象所有权Cocoa与O__ective-C特性o成员变量应该为@privateo指明指定的初始化器o重写指定的初始化器o避免使用+newo保持公有的API尽量简单o#import与#includeo使用根框架o创建对象时尽量使用autoreleaseoAutorelease之后retainoDealloc中应该按声明的顺序处理成员变量oSetters中对NSString进行copyo避免抛出异常onil的检查oBOOL陷阱o属性Cocoa模式o委托模式o模型-视图-控制器背景介绍O__ective-C是一种动态的面向对象的语言,它是C的扩展它被设计成具有易读易用的,支持复杂的面向对象设计的编程语言它是__cOSX以及iPhone的主要__语言Cocoa是__cOSX的主要的应用程序框架它由一组支持__cOSX全部特性的,并可用于快速__的O__ective-C类构成ApplesCocoaCodingGuidelinesGooglesOpenSour__C++StyleGuide本文档的目的在于为所有的__cOSX的代码提供编程指南及最佳实践许多指南是在实际的项目及小组中经过__的演进及验证的请注意,本指南不是O__ective-C的教程我们假定读者已经对O__ective-C非常熟悉如果你刚刚接触O__ective-C或者需要提高,请阅读TheO__ective-CProgrammingLanguage例子一个例子顶上一千句话,我们就从这样的一个例子开始,来__一下编码的风格、空格以及命名等等一个头文件的例子,展示了在@inte_____声明中如何进行正确的注释以及空格// GTMFoo.h// FooProject//// CreatedbyGregMilleron6/13/
08.// Copyright2008GoogleInc.Allrightsreserved.//#importfoundation/foundation.h//AsampleclassdemonstratinggoodO__ective-Cstyle.Allinte_____s//categoriesandprotocolsread:alltop-leveldeclarationsinaheader//MUSTbecommented.Commentsmustalsobeadja__nttotheo__ecttheyre//documenting.////noblanklinebetweenthiscommentandtheinte_____@inte_____GTMFoo:NSO__ect{@privateNSString*foo_;NSString*bar_;}//Returnsanautoreleasedinstan__ofGMFoo.See-initWithString:fordetails//abouttheargument.+idfooWithString:NSString*string;//Designatedinitializer.|string|willbecopiedandassignedto|foo_|.-idinitWithString:NSString*string;//Getsandsetsthestringfor|foo_|.-NSString*foo;-voidsetFoo:NSString*newFoo;//Doessomeworkon|blah|andreturnsYESiftheworkwascompleted//suc__ssfulyandNOotherwise.-BOOLdoWorkWithString:NSString*blah;@end/foundation一个实现文件的例子,展示了@implementation部分如何进行正确的注释、空格同时也包括了基于引用实现的一些重要方法,如getters、setters、init以及dealloc//// GTMFoo.m// FooProject//// CreatedbyGregMilleron6/13/
08.// Copyright2008GoogleInc.Allrightsreserved.// #importGTMFoo.h @implementationGTMFoo +idfooWithString:NSString*string{return[[[selfalloc]initWithString:string]autorelease];} //Mustalwaysoverridesupersdesignatedinitializer.-idinit{return[selfinitWithString:nil];} -idinitWithString:NSString*string{ifself=[superinit]{foo_=[stringcopy];bar_=[[NSStringalloc]initWithFor__t:@hi%d3];}returnself;} -voiddealloc{[foo_release];[bar_release];[superdealloc];} -NSString*foo{returnfoo_;} -voidsetFoo:NSString*newFoo{[foo_autorelease];foo_=[newFoocopy];} -BOOLdoWorkWithString:NSString*blah{//...returnNO;}@end空格与格式空格与制表符我们使用空格进行缩进不要在代码中使用制表符你应该将你的文本编辑器设置成自动将制表符替换成空格总结只使用空格,每次缩进四个空格行宽即使O__ective-C比C++更加冗长,为了保证本指南的可操作性,我们决定保持每行宽度为80列这比你想的要简单我们意识到这条规则是有争议的,但很多已经存在的代码坚持了本规则,因此我们觉得保证一致性更重要通过设置XcodePreferen__sTextEditingShowpageguide,来使越界更容易被发现总结代码中的每行最多有80个字符方法声明与定义方法应该像这样-voiddoSomethingWithString:NSString*theString{ ...} 星号前的空格是可选的统一要求加空格当写新的代码时,要与原的代码一致如果一行有非常多的参数,更好的方式是将每个参数单独拆成一行如果使用多行,将每个参数前的冒号对齐-voiddoSomethingWith:GTMFoo*theFoo rect:NSRecttheRect interval:floattheInterval{...} 当第一个关键字比其它的短时,保证下一行至少有4个空格的缩进这样可以使关键字垂直对齐,而不是使用冒号对齐-voidshort:GTMFoo*theFoolongKeyword:NSRecttheRectevenLongerKeyword:floattheInterval{...}总结-或者+与返回类型之间,需要有空格参数列表中,只有参数之间有空格方法调用方法调用时,所有参数应该在同一行[myO__ectdoFooWith:arg1name:arg2error:arg3];或者每行一个参数,以冒号对齐[myO__ectdoFooWith:arg1 name:arg2 error:arg3];不要使用下面的缩进风格[myO__ectdoFooWith:arg1name:arg2 //somelineswith1arg error:arg3]; [myO__ectdoFooWith:arg1 name:arg2error:arg3]; [myO__ectdoFooWith:arg1name:arg2 //aligningkeywordsinsteadofcolonserror:arg3];方法定义与方法声明一样,当关键字的长度不足以以冒号对齐时,下一行都要以四个空格进行缩进[myO__short:arg1longKeyword:arg2evenLongerKeyword:arg3];总结方法定义的格式与方法声明的格式非常相似当格式的风格有多种选择时,新的代码要与已经存在的代码保持一致@public与@private与C++中的publicprivate以及protected非常相似@inte_____MyClass:NSO__ect{@public...@private...}@end总结@public以及@private访问标识符应该以一个空格缩进异常如果你必须使用O__ective-C的异常,按下面的格式进行编码代码然后,请参见避免抛出异常来了解不应该使用异常的原因@try{ foo;}@catchN_____ption*ex{ barex;}@finally{ baz;}总结每个@标签应该有__的一行,在@与{}之间需要有一个空格@catch与被捕捉到的异常对象的声明之间也要有一个空格协议这条规则也同样适用于类声明、成员变量以及方法声明例如@inte_____MyProtocoledClass:NSO__ectnswindowdelegate{@privateidmyfancydelegatedelegate_;}-voidsetDelegate:idmyfancydelegateaDelegate;@end/myfancydelegate/myfancydelegate/nswindowdelegate总结尖括号所包括的协议名称与前面的类型标识之间不应该有空格命名对于可维护的代码,命名规则非常重要O__ective-C的方法名往往十分长,但代码块读起来就像散文一样,不需要太多的注释修饰当编写纯O__ective-C代码时,我们基本遵守标准的O__ective-Cnamingrules,这些命名规则可能与C++风格指南中的大相径庭例如,Google的C++风格指南中推荐使用下划线分隔的单词作为变量名,而苹果的风格指南则使用camel命名法,这在O__ective-C社区中非常普遍任何的类、分类、方法以及变量的名字中都使用全大写缩写这遵守了苹果的标准命名方式,如URL、TIFF以及EXIF当编写O__ective-C++代码时,事情就不这么简单了许多的项目需要实现跨平台的C++代码,并与O__ective-C以及Cocoa混合编写或者以C++作为后端,Cocoa作为前端这就导致了两种命名方式直接不统一我们的解决方案是编码风格取决于方法/函数以哪种语言实现如果在一个@implementation语句块中,就使用O__ective-C的风格如果实现一个C++的类,请使用C++的风格这避免了成员变量与局部变量使用混合的命名风格,这会严重地影响可读性文件名文件的扩展名应该如下.hC/C++/O__ective-C的头文件.mOjbective-C实现文件.mmOjbective-C++的实现文件.cc纯C++的实现文件.c纯C的实现文件分类的文件名应该包含被扩展的类的名字,如GTMNSString+Utils.h或GTMNSTextView+Autocomplete.h总结文件名应该反映了它实现了什么类遵守你的项目的惯例O__ective-C++为了最小化Cocoa/O__ective-C与C++之间的命名风格的冲突,按照下面方法实现的风格编写代码在实现@implementation语句块时,使用O__ective-C的命名规则;如果实现一个C++的类,就使用C++命名规则//file:cross_platform_header.hclassCrossPlatfor__PI{public: ... intdoSomethingPlatformSpecific; //imploneachplatformprivate: intm_anInstan__Var;};//file:__c_implementation.mm#includecross_platform_header.h//AtypicalO__ective-CclassusingO__ective-Cnaming.@inte_____MyDelegate:NSO__ect{@private intinstan__Var_; CrossPlatfor__PI*backEndO__ect_;}-voidrespondToSomething:idsomething;@end@implementationMyDelegate-voidrespondToSomething:idsomething{ //bridgefromCocoathroughourC++backend instan__Var_=backEndO__ect-DoSomethingPlatformSpecific; NSString*tempString=[NSStringstringWithInt:instan__Var_]; NSLog@%@tempString;}@end//Theplatform-specificimplementationoftheC++classusing//C++naming.intCrossPlatfor__PI::doSomethingPlatformSpecific{ NSString*strTempString=[NSStringstringWithInt:anInstan__Var_]; NSLog@%@strTempString; return[strTempStringintValue];}总结当编写源代码时,Ojbective-C++应该采用你正在实现的方法/函数的风格类名应用程序级的代码,应该尽量避免不必要的前缀为每个类都添加前缀不会提高任何的可读性当设计跨不同应用程序的代码时,应该使用前缀,例如GTMSendMessage总结类名、分类名、协议名应该以大写字母开始,并混合小写字母来分隔单词Camel命名法分类名例如,录我们要创建一个NSString的类别以解析时,我们将把类别放在一个名为GTMNSString+Parsing.h的文件中类别名本身的名字是GTMStringParsingAdditions(是的,我们知道类别名和文件名不一样,但是这个文件中可能存在多个不同的与解析有关类别)类别中的方法应该以gtm_myCategoryMethodOnAString为前缀以避免命名冲突,因为O__ective-C只有一个命名空间如果代码不会被__并且不会被运行在不同的地址空间中,方法名字就不那么重要类名与包含类别名的括号之间,应该以一个空格分隔总结类别名应该有两三个字母的前缀以表示类别是项目的一部分或者该类别是通用的类别应该包含它所扩展的类的名字O__ective-C方法名方法名应该读起来就像句子,这表示你应该选择与方法名连在一起读起来通顺的参数名例如,convertPoint:fromRect:orrepla__CharactersInRange:withString:参见ApplesGuidetoNamingMethods访问器方法应该与他们getting的的成员变量的名字一样,但不应该以get作为前缀例如-idgetDelegate; //__OID-iddelegate; //GOOD这仅限于O__ective-C的方法名C++的方法与函数的命名规则应该遵从C++风格指南中的规则总结方法名应该以小写字母开头,并混合大小写(Camel命名法)每个命名的参数也应该以小写字母开头变量名常用变量名对于静态的类别,如int以及指针等,不要使用匈牙利命名法要为变量起一个描述性的名字不要担心浪费列宽,因为让新的代码阅读者立即理解你的代码更重要例如错误的命名intw;intnerr;intnCompConns;tix=[[N__utableArrayalloc]init];o__=[someO__ecto__ect];p=[networkport];正确的命名intnumErrors;intnumCompletedConnections;tickets=[[N__utableArrayalloc]init];userInfo=[someO__ecto__ect];port=[networkport];成员变量成员变量应该混合大小写,并以m加下划m_线作为前缀,如m_userNameTextField然而,如果不能使用O__ective-C
2.0(操作系统版本的限制),并且使用KVO/KVC绑定成员变量时,我们允许这个例外(译者注KVO=KeyValueObserving,KVC=KeyValueCoding)这种情况下,可以以一个下划线作为成员变量名字的前缀,这是苹果所接受的键/值命名惯例如果可以使用O__ective-C
2.0,@property以及@synthesize提供了遵从这一命名规则的解决方案常量常量名(如宏、枚举、静态局部变量等)应该以小写字母k开头,使用混合大小写的格式来分隔单词,如kInvalidHandle,kWritePerm总结变量名应该以小写字母开头,并混合大小写类的成员变量应该以m_作为前缀例如myLocalVariable、m_myInstan__Variable如果不能使用O__ective-C
2.0的@property,使用KVO/KVC绑定的成员变量可以以一个下划线作为前缀注释虽然写起来很痛苦,但注释是保证代码可读性的关键下面的规则给出了你应该什么时候、在哪进行注释记住尽量注释很重要,但最好的代码应该自成文档与其给类型及变量起一个晦涩难懂的名字,再为它写注释,不如直接起一个有意义的名字当你写注释的时候,记得你在给你的听众写,即下一个需要阅读你的代码的代码贡献者大方一点,下一个读代码的人可能就是你!记住所有C++风格指南里的规则在这里也同样适用,不同的地方会在下面指出文件注释版权信息及__每个文件应该按顺序包括如下内容版权信息声明(如Copyright2008GoogleInc.)授权样版选择一个合适的项目所使用的授权样板(例如,Apache
2.0BSDLGPLGPL)如果你对其他人的原始代码作出重大的修改,请把你的名字添加到__里面当另外一个代码贡献者对文件有问题时,他需要知道怎么__你,这十分有用总结以版权信息作为文件头部,开始每一个文件,后接文件内容的描述声明注释//AdelegateforNSApplicationtohandlenotificationsaboutapp//launchandshutdown.Ownedbythe__inappcontroller.@inte_____MyAppDelegate:NSO__ect{ ...}@end如果你已经在文件头部详细描述了接口,可以直接说明“完整的描述请参见文件头部”,但是一定要有这部分注释另外,公共接口的每个方法,都应该有注释来解释它的作用、参数、返回值以及其它影响为类的线程安全性作注释,如果有的话如果类的实例可以被多个线程访问,记得注释多线程条件下的使用规则总结每个接口、类别以及协议应该注释,以描述它的目的及作用实现注释这会避免二义性,尤其是当符号是一个常用词汇,这使用语句读起来很糟糕例如,对于符号count//Sometimesweneed|count|tobelessthanzero.或者当引用已经包含引号的符号//Remembertocall|StringWithoutSpa__sfoobarbaz|总结使用|来引用注释中的变量名及符号名而不是使用引号对象所有权继承自NSO__ect的成员变量指针,通常被假定是强引用关系(retained)如果它有没被类retained,应该注释为弱引用(weak)然而,以IBOutlets作为标签的成员变量默认是不会被类retained的如果是强引用关系,应该注释当成员变量指向CoreFoundation、C++或者其它非O__ective-C对象时,无论是强引用还是弱引用,都需要注释说明注意O__ective-C对象中的C++对象的自动封装,默认情况下是不允许的,参见强引用及弱引用注释的例子@inte_____MyDelegate:NSO__ect{@private IBOutletN__utton*okButton_; //nor__lNSControl IBOutletN__enu*myContextMenu_; //__nually-loadedmenustrong AnO__cO__ect*doohickey_; //mydoohickey MyController*controller_;//sowecansendmsgsbackweakownsme //non-NSO__ectpointers... __ackyCPPClass*wacky_; //somecross-platformo__ectstrong CFDictionaryRef*dict_; //strong}@end强引用对象被类retained弱引用对象没有被类retained(如委托)总结当与O__ective-C最通常的作法不同时,尽量使用指针的所有权模型尽量直观Cocoa以及O__ective-C特性成员变量应该为@private@inte_____MyClass:NSO__ect{@private idmyInstan__Variable_;}//publicac__ssorssettertakesownership-idmyInstan__Variable;-voidsetMyInstan__Variable:idtheVar;@end总结成员变量应该声明为私有指明指定的初始化器对于需要继承你的类的人来说,指定的初始化器十分重要这样他们就可以只重写一个初始化器(可能是几个)来保证他们的子类的初始化器会被调用这也有助于将来别人调试你的类时,理解初始化代码的工作流程总结注释并且明确指出你的类的指定的初始化器重写指定的初始化器如果___重写父类的指定的初始化器,你的初始化器有时可能不会被调用,这会导致很微妙而且难以解决的bug总结当你写子类的时候,如果需要init...方法,记得重写父类的指定的初始化器初始化刚分配的对象,默认值都是0除了isa指针(译者注NSO__ect的isa指针,用于标识对象的类型)所以不要在初始化器里面写一堆将成员初始化为0或者nil的代码总结不要在init方法中,将成员变量初始化为0或者nil,这是冗余的避免使用+new现代的Ojbective-C代码通过调用alloc和init方法来创建并且retain一个对象由于类方法new很少被使用,这使得有关内存分配的代码审查更困难总结不要调用NSO__ect类的类方法new,也不要在子类重写相反,你应该使用alloc和init方法来创建并初始化一个对象保持公有的API尽量简单与C++不同,O__ective-C没有方法来区分公有的方法和私有的方法,所有的方法都是公有的(译者注这取决于O__ective-C运行时的方法调用的消息机制)因此,除非客户端的代码期望使用某个方法,不要把这个方法放进公有的API中这降低了你不希望被调用的方法被调用的可能性这包括重写父类的方法对于内部实现所需要的方法,在实现的文件中定义一个类别,而不是把它们放进公有的头文件中//GTMFoo.m#importGTMFoo.h@inte_____GTMFooPrivateDelegateHandling-NSString*doSomethingWithDelegate; //Declareprivatemethod@end@implementationGTMFooPrivateDelegateHandling...-NSString*doSomethingWithDelegate{ //Implementthismethod}...@end在O__ective-C
2.0之前,如果你在私有的@inte_____中声明了某个方法,但在@implementation中忘记定义了这个方法,编译器不会__(这是因为你没有在其它的类别中实现这个私有的方法)解决文案是将方法放进指定类别的@implemenation中如果你在使用O__ective-C
2.0,相反你应该使用类扩展来声明你的私有类别,例如@inte_____GMFoo{...}这会保证如果声明的方法没有在@implementation中实现,会产生一个编译器警告再次说明,私有的方法其实不是私有的你有时可能不小心重写了父类的私有方法,这很难调试通常,私有的方法应该有一个相当特殊的名字以防止子类无意地重写它们Ojbective-C的类别是一种很好的方法来将一个大的@implementation拆分成更容易理解的小块同时,类别可以为最适合的类添加新的、基于特定应用程序的功能例如,当添加一个“middleTruncation”方法时,创建一个NSString的新类别并把方法放在里面,比创建任意的一个新类把方法放进里面要好得多#import与#include基于你所包括的头文件的编程语言,选择使用#import还是#include当包含一个使用O__ective-C、O__ective-C++的头文件时,使用#import当包含一个使用标准C、C++头文件时,使用#include头文件应该提供自己的一些Ojbective-C的头文件缺少#define保护,只期望被使用#import的方式包含由于O__ective-C的头文件只会被O__ective-C的源文件及头文件包含,广泛地使用#import是可以的文件中没有O__ective-C的标准C、C++的头文件,可能会被普通的C、C++包含既然标准的C、C++里面没有#import的用法,这些文件将被#include包含O__ective-C源文件中使用#include包含,意味着这些头文件会永远以相同的语义被包含这条规则帮助跨平台的项目中产生无意的错误一个忘记使用#define保护的__c__者,在引用了新的C、C++头文件时,如果新的头文件使用#import被引用,在__c上会没有问题但在其它使用#include平台上可能会使构造失败一致地在所有的平台上使用#include,意味着构造更可能一致地成功或者失败这避免了文件只能在某些平台上使用的尴尬下面是正确的使用方式#importcocoa/cocoa.h=#includecorefoundation/corefoundation.h=#importGTMFoo.h#includebase/basictypes.h/corefoundation/cocoa总结#importOjbective-C/O__ective-C++头文件,#includeC/C++头文件使用根框架当你试图从框架(如Cocoa或者Foundation)中包含单独的系统头文件时,实际上包含顶级根框架编译器要作更少的工作根框架通常被预编译,并且加载得更快另外记得使用#import而不是#include来包含O__ective-C的框架正确的做法#importfoundation/foundation.h //good/foundation错误的做法#importfoundation/nsarray.h //__oid#importfoundation/nsstring.h.../foundation/foundation总结包含根框架而不是单独的文件创建对象时尽量使用autorelease尽管运行效率会差一点,这避免了意外地删除了release或者插入return语句而产生内存泄露的可能例如错误的做法//__OIDunlessyouh__eacompellingperfor__n__reasonMyController*controller=[[MyControlleralloc]init];//...codeherethatmightreturn...[controllerrelease];正确的做法//BETTERMyController*controller=[[[MyControlleralloc]init]autorelease];总结当创建临时对象时,在同一行使用autolease,而不是在同一个方法的后面语句中使用一个单独的releaseAutolease之后retain当给一个变量赋值新的对象时,必须先释放掉旧的对象以避免内存泄露有一些正确的方法来处理它的循环会填满autoreleasepool,并且可能效率上会差一点,但这点折衷我们认为我们选择autorelease之后retain的方法因为事实证明它更少地出错注意大是可以接受的-voidsetFoo:GMFoo*aFoo{ [foo_autorelease]; //Wontdeallocif|foo_|==|aFoo| foo_=[aFooretain];}总结给对象赋值时遵守autorelease之后retain的模式Dealloc中应该按声明的顺序处理成员变量代码审查者在审查新的或者修改过的dealloc实现时,需要保证每个retained的对象都得到了释放为了简单的审查dealloc,对象被释放的顺序应该与他们在@inte_____中声明的顺序一致如果dealloc调用了其它方法释放成员变量,注释这个方法处理了哪些成员变量的释放总结dealloc中对象被释放的顺序应该与他们在@inte_____中声明的顺序一致,这有助于代码审查Setters中对NSString进行copy永远不要仅仅retain一个字符串这避免了调用者在_____情况下对字符串作出了修改不要作出那样的假设你接受的对象是一个NSString对象而不是N__utableString对象-voidsetFoo:NSString*aFoo{ [foo_autorelease]; foo_=[aFoocopy];}总结接受NSString作为参数的setter,应该copy它所接受的字符串避免抛出异常我们确实在编译时允许-fo__c-ex__ptions(主要我们得到了使用@synchronized的好处),但我们不使用@throw当正确地使用第三方的代码时,使用@try、@catch、和@finally是允许的如果你确实使用了异常,请注释你期望什么方法抛出异常不要使用NS_DURINGNS_HANDLERNS_ENDHANDLERNS_VALUERETURN和NS_VOIDRETURN这些宏,除非你写的代码需要在__cOSX
10.2或者之前的操作系统中运行注意当使用O__ective-C++写基于栈的对象的代码时,如果抛出O__ective-C异常,对象不会被清理例如classex__ptiontest{public: ex__ptiontest{NSLog@Created;} ~ex__ptiontest{NSLog@Destroyed;}}; voidfoo{ ex__ptiontesta; N_____ption*ex__ption=[N_____ptionex__ptionWithName:@foo reason:@bar userInfo:nil]; @throwex__ption;} int__inintar__char*argv[]{ G__utoreleasePoolpool; @try{ foo; } @catchN_____ption*ex{ NSLog@ex__ptionraised; } return0;}会输出12006-09-2812:34:
29.244ex__ptiontest
[23661]Created22006-09-2812:34:
29.244ex__ptiontest
[23661]ex__ptionraised注意这里析构函数从未被调用这主要会影响基于栈的对象如shared_ptr、linked_ptr和所有你可能使用的STL对象你永远不应该重新抛出O__ective-C异常,也不应该在@try@catch@finally语句块中使用基于栈的C++对象总结不要抛出O__ective-C异常,但准备从第三方的调用或者系统调用捕捉异常nil的检查使用nil的检查来检查应用程序的逻辑,而不是避免崩溃O__ective-C运行时会处理向一个nil的对象发送消息的情况如果方法没有返回值,就没关系如果有返回值,可能由于运行时架构、返回值类型以及OSX版本的不同而不同,参见Applesdocumentation注意,这与检查C/C++的指针是否为NULL非常不同,运行时不会检查空的情况,并导致你的应用程序崩溃你仍然需要保证你不会对一个C/C++的空指针解引用总结nil检查只用于逻辑流的判断BOOL陷阱Ojbective-C中定义BOOL为无符号字符型,这意味着BOOL类型可以有不同于YES1或者NO0)的值不要直接把整形转换成BOOL常见的错误包括将数组的大小、指针值及位运算的结果直接转换成BOOL,这取决于整型结果的最后一个字节,可能产生一个NO的值当转换整形至BOOL时,使用三目操作符来返回YES或者NO译者注读者可以试一下任意的256的整数的转换结果,如
256、
512...对BOOL使用逻辑运算符(||和!)是合法的,返回值也可以安全地转换成BOOL,不需要使用三目操作符错误的用法-BOOLi__old{ return[selffontTraits]NSFontBoldTrait;}-BOOLisValid{ return[selfstringValue];}正确的用法-BOOLi__old{ return[selffontTraits]NSFontBoldTraitYES:NO;}-BOOLisValid{ return[selfstringValue]!=nil;}-BOOLisEnabled{ return[selfisValid][selfi__old];}同样的,不要直接___OOL变量与YES/NO不仅仅这影响可读性,结果可能与你想的不同错误的用法BOOLgreat=[fooisGreat];ifgreat==YES //...begreat!正确的用法BOOLgreat=[fooisGreat];ifgreat //...begreat!总结将常规整形转换成BOOL时要小心,不要直接将BOOL值与YES进行比较属性命名属性所关联的成员变量的命名必须遵守以下划线作为后缀的规则属性的名字应该与成员变量去掉下划线后缀的名字一模一样使用@synthesize指示符来正确地重命名属性@inte_____MyClass:NSO__ect{@private NSString*name_;}@propertycopynonatomicNSString*name;@end @implementationMyClass@synthesizename=name_;@end位置类接口中的属性的声明必须紧跟着成员变量语句块属性的定义必须在@implementation的类定义的最上方他们的缩进与包含他们的@inte_____以及@implementation语句一样@inte_____MyClass:NSO__ect{@private NSString*name_;}@propertycopynonatomicNSString*name;@end @implementationMyClass@synthesizename=name_;-idinit{...}@endNSString使用copy特性NSString属性应该永远被声明为copy特性这从逻辑上遵守了NSString的setter必须使用copy而不是retain不要synthesizeCFType的属性CFType应该永远使用@dynamic实现指示符尽管CFType不能使用retain属性特性,__者必须自己处理retain和release很少有情况你需要仅仅对它进行赋值,因此最好显示地实现getter和setter,并作出注释说明列出所有的实现指示符尽管@dynamic是默认的,显示列出它以及其它的实现指示符会提高可读性,代码阅读者可以一眼就知道类的每个属性是如何实现的错误的做法@inte_____MyClass:NSO__ect@propertyreadonlyNSString*name;@end @implementationMyClass-NSString*name{ return@foo;}@end正确的做法@inte_____MyClass:NSO__ect@propertyreadonlyNSString*name;@end @implementationMyClass@dynamicname;-NSString*name{ return@foo;}@end原子性一定要注意属性的开销所有synthesize的setter和getter都是原子的这会给每个get或者set带来一定的同步开销显示将你的属性声明为nonatomic除非你需要原子操作点引用点引用是地道的O__ective-C
2.0的风格它被使用于简单的属性set、get操作,但对象的其它行为不应该使用它正确的做法NSString*oldName=myO__ect.name;myO__ect.name=@Ali__;错误的做法NSArray*array=[[NSArrayarrayWithO__ect:@hello]retain]; NSUIntegernumberOfItems=array.count; //notapropertyarray.release; //notaproperty总结需要注意的是,使用点引用语法必须需要O__ective-C
2.0的支持,这意味着你的代码只能运行于iPhone或者__cOSX
10.5Leopard及以后的版本点引用只允许访问声明的属性Cocoa模式委托模式实现委托模式的类应该拥有一个名为delegate_的成员变量来引用委托因此,访问器方法应该名为delegate和setDelegate:delegate_对象不应该被retained总结委托对象不应该被retained模型-视图-控制器模型与视图分离不要假设模型或者数据源的表示方法保持数据源与表示层之间的接口抽象视图不需要了解模型的逻辑(主要的规则是问问你自己,对于数据源的一个实例,有没有可能有多种不同状态的表示方法)控制器与模型、视图分离不要把所有的“领域逻辑”放进跟视图有关的类中这命名得代码非常难以重用使用控制器来写这些代码,但保证控制器不需要了解太多表示层的逻辑使用@protocol来定义回调API,如果不是所有的方法都必须实现,使用@optional(例外当使用O__ective-C
1.0,@optional不可用,因此请使用类别来定义“非正式的协议”)总结分离模型与视图分离控制器与视图、模型回调API使用@protocol。