1.除非有必要,否则不要引用头文件,一般来说应该利用@class使用前向声明,并在实现中引用头文件;如果实在无法使用,比如要
声明某个类遵循一项协议,这种情况下,尽量把这条声明移到分类中,如果不行的话,就把协议单独放到一个头文件中,然后再引入
2.应该使用字面量语法来创建字符串、数值、数组、字典,这样做更加简明扼要;应该通过小标操作来访问数组或字典中的值;需要
注意的是,采用字面量语法,若值有nil,会抛出异常。
3.不用使用预处理指令定义常量;在实现文件中用static
const来定义内部常量(以k开通),这样就不会出现在全局符号表中;在头文
件中使用extern来声明全局常量,并在相关实现文件中定义其值,他会出现在全局符号表中,所以其名称应加以区别,通常用与之相关
的类名做前缀
4.用NS_ENUM与NS_OPTIONS宏来定义枚举类型,并指明其底层数据类型,确保枚举类型底层数据类型的可控性; 其语法为:
typedef
NS_ENUM(NSUInteger,xxx){};
typedef NS_OPTIONS(NSInteger,YYY){};
5.可以用@property语法来定义对象中所封装的数据,并通过atomic/nonatomic/readwrite/readonly/assign/unsafe_unretained/strong/
weak/copy等特性来指定存储数据所需的正确定义,还可以在声明@property的时候利用getter=<name>和setter=<name>来指定其相应的方法
名;并且在设置属性所对应的实例变量时,一定要遵从该属性所声明的语义
6.在对象内部读取数据时,应该直接通过实例变量来读,而写入数据时,则应通过属性来写;在初始化及dealloc方法中,应该通过实例变量来读取数据,
防止子类因为对属性方法的重载导致的问题;如果使用惰性初始化技术的数据,必须通过属性来读取数据
7.若要想检测对象的等同性,请提供isEqual与hash方法,对于内置对象,已经提供了isEqualToArray/isEqualToDictionary/isEqualToString方法;
并且要清楚hash相等只是一个必要而非充分的条件;不要盲目地逐个检测每条属性,而是应该按照具体需求来制定检测方案
8.所谓的类族就是把实现细节隐藏在一套简单的公共接口里面,基类实现类方法;系统框架中经常使用类族,所在要小心的是
你所想要的类也许是该类的子类,故就不能用isMemberOfClass或==来做判断,而应该采用isKindOfClass来做判断
9.所谓关联对象就是把对象当成NSDictionary来存储key-value,用方法:objc_setAssociatedObject/objc_getAssociatedObject/
objc_removeAssociatedObject全句方法来完成设置/获取/删除;他有相应的关联类型:
OBJC_ASSOCIATION_ASSIGN
OBJC_ASSOCIATION_RETAIN_NONATOMIC
OBJC_ASSOCIATION_COPY_NONATOMIC
OBJC_ASSOCIATION_RETAIN
OBJC_ASSOCIATION_COPY
想要注意的是,只有在其他做法不可行时才应选用关联对象,因为这种做法通常会引入难于查找的BUG,一般都可以继承实现子类的方法来解决
10.利用objc_msgSend/objc_msgSend_stret/objc_msgSend_fpret/objc_msgSendSuper来实现动态消息派发系统,
当给某对象发送消息时,该系统会查出对应的方法,在该对象上调用其C代码
11.消息转发流程包含三个部分:resolveInstanceMethod->forwardingTargetForSelector->forwardInvocation,对应第一步可以实现对
@dynamic属性的设置,第二步可以实现类似多继承的方式,第三步会封装NSInvocation对象,进行完整的消息派发流程;故步骤越往后,
处理消息的代价越大,如果第一步处理完,就可以缓存,后续访问直接就可以返回而不需要启动消息转发流程,第二步可以以组合的方
式来实现多继承,第三步由于要创建NSInvocation对象,消耗最大;需要用到辅助函数NSStringFromSelector来将方法名转成字符串,另外,
利用class_addMethod来动态添加成员方法
Objective-C Effective 技巧,布布扣,bubuko.com
原文:http://www.cnblogs.com/fuland/p/3667182.html