《Effective Objective 2.0 读书笔记》
1 类的头文件中尽量少引入其它头文件,使用“向前声明” @class,这样可以降低类之间的耦合
2 多用字面量语法,缩减代码长度,易读
NSNumber *number = @10086;
NSArray *books = @[@"数据结构与算法",@"java实战"];
NSDictionary *dic = @{@"name":@"金龙鱼",
@"age":@18,};
3 在读取实例变量的时候采用直接访问的形式,而在设置实例变量的时候通过属性来做(对象内部)
原因如下:
- 直接访问实例变量速度快的原因是不经过Objective-C的“方法派发”)
- 通过属性访问有助于大断点排查问题
- 不会触发“键值观测”
- 在初始化方法及delloc方法中,总是应该直接通过实例变量来读写数
4 多用类型常量,少用 #define 预处理指令(宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误。)
const NSString *kDebugLoginAccount = @"kDebugLoginAccount" const NSString *kDebugLoginPassword = @"kDebugLoginPassword" const NSString *SAVE_PASSWORD_KEY= @"SAVE_PASSWORD_KEY"
5 命名时使用前缀避免命名空间冲突
1 类命名
2 分类命名/分类方法命名
3 类的实现文件中所用的纯C函数及全局变量
4 给私有方法的名称加上前缀,这样可以很容易的将其同公共方法区分开。
6 尽量使用不可变对象
- 尽量创建不可变对象。
- 若某属性仅可以在对象内部修改,则在
class-continuation分类
中将其由readonly
属性扩展为readwrite
属性。 - 不要把可变的
collection
作为属性公开,而应提供相关方法,以此修改对象中的可变collection
7 NSCopying协议
(1) 在Objective-C语法中,NSString默认实现了NSCopying协议,其它对象则没有实现此协议。若想自己所写的对象具有拷贝功能,只需遵循NSCopying协议,并实现其中的方法即可。
(2) 如果自定义的对象分为可变版本与不可变版本,那么就要同时实现NSCopying和NSMutableCopying协议。
(3)复制对象时需要决定采用浅拷贝还是深拷贝,一般情况下应尽量执行浅拷贝
@interface CXLPerson : NSObject<NSCopying> @property (nonatomic,copy,readonly) NSString *firstName; @property (nonatomic,copy,readonly) NSString *lastName; - (id)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName; @end ... @implementation CXLPerson{ NSMutableSet *_friends; } #pragma mark - Init Menthod - (id)initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName{ self = [super init]; if (self) { _firstName = firstName; _lastName = lastName; _friends = [NSMutableSet new]; } return self; } - (id)copyWithZone:(NSZone *)zone{ CXLPerson *person = [[[self class] alloc]initWithFirstName:_firstName lastName:_lastName]; //注意这里使用 -> 语法,因为_friends并非属性,只是个在内部使用的实例变量。 person -> _friends = [_friends mutableCopy]; return person; } @end
8 在dealloc方法中只释放引用并解除监听
- 在每个对象的生命周期内,此方法仅执行一次。
- 在dealloc方法里,应该做的事情就是释放指向其他对象的引用,并取消原来订阅的KVO和NSNotificationCenter等通知,不要做其他事情。
9 以 “自动释放池块” 降低内存峰值
- 自动释放池排布在栈中,对象收到
autorelease
消息后,系统将其放入最顶端的池里。 - 合理运用自动释放池,可降低应用程序的内存峰值。
@autoreleasepool
这种新式写法能创建出更为轻便的自动释放池。
10 多用GCD,少用performSelector系列方法
如果想把任务放在另一个线程上执行,那么最好不要使用performSelector系列方法,而是应该把任务封装到块里,然后调用大中枢派发机制的相关方法来实现。
11 构建缓存时使用NSCache而非NSDictionary
- 当系统资源将要耗尽时,NSCache可以自动删除缓存。
- NSCache还会先行删除最久未使用的对象。
- NSCache是线程安全的,而NSDictionary则绝对不具备此优势。
- 可以给NSCache对象设置上限,用于限制缓存中的对象总个数及“总成本”,而这些尺度则定义了缓存删减其中对象的时机。
12 简化initalize 与 load的实现代码
两个方法的主要区别如下:
(1)load在程序运行后立即执行,且只调用一次;initalize在类的方法第一次被调用时执行,且只调用一次
(2)若子类未实现load方法,load不会调用父类的方法,initalize则相反
13 为第三方类的分类名称添加前缀
由于运行期系统会把分类中所实现的每个方法都加入类的方法列表中,如果类中本来就有此方法,而分类又实现了一次,那么分类中的方法会覆盖原来的那一份代码,所以我们在新建分类及方法时应如下:
(1)向第三方类中添加分类时,总应给其名称加上你专用的前缀。
(2)向第三方类中添加分类时,总应给其中的方法名加上你专用的前缀。