《Effective Objective-C 2.0编写高质量iOS与OS X代码的52个有效方法》读书笔记(上)
Posted WoodBear009
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《Effective Objective-C 2.0编写高质量iOS与OS X代码的52个有效方法》读书笔记(上)相关的知识,希望对你有一定的参考价值。
1.OC对象所占内存总是分配在"堆"中,而绝不会分配在"栈"中,不能再栈中分配OC对象。"栈"中对象借助栈帧进行维护,"堆"中对象的管理借助引用计数机制.
-(NSMutableArray *)test
//ary指针本身在栈上,但分配的数组对象在堆上,这也就解释了,为什么函数返回后,ary会随着栈帧弹出而被释放,
//但外部依然能使用NSMutableArray,因为NSMutableArray本身在堆上,依赖引用计数机制进行维护
NSMutableArray *ary = [[NSMutableArray alloc] init];
return ary;
2.如非必须知道某类的细节,尽量避免头文件的引入,可提高编译效率,降低类之间耦合。尽量把协议单独定义到一个头文件中,同样是为了提高编译效率,减少不必要内容的编译。
3.多用字面量语法
使用字面量语法创建出来的字符串、数组、字典等都是不可变的。若想要可变的,需要mutableCopy一份(要注意深、浅、完全拷贝的概念)。
NSNumber *num = @1;
NSArray *ary = @[@"1",@"2",@"3"];
NSDictionary *dict = @@"1":@1,@"2":@2;
4.多用类型常量,少用#define。预处理指令定义的常量不含类型信息,编译器不做检验。
5.多用枚举.(1)表意清晰 (2)按位或(与)操作定义枚举技巧 (3)用NS_ENUM(不需要组合)或NS_OPTIONS(需要组合)来定义枚举,可以确保枚举值的类型 (4)switch枚举值时不要实现default,可借助编译器提示有枚举未处理
6.读取实例变量时尽量采用直接访问,可以绕过方法调用(派发),但不会触发KVO.设置(写)时通过属性进行,使存方法(控制)发挥作用。
7.对象同等性。==判断是指针是否指向了同一对象。
isEqual:建立于hash基础上,isEqual->YES->hash相同;反之hash相同!->isEqual->YES.
isEqual可能包含以下判断:(1).是否本身就是同一对象 (2).是否是同一类对象 (3).各属性(具体判断根据实际需求实现)是否相等
isEqualToString这类方法相较isEqual,省略了类型的检测,提高了效率
注意isEqual的判定深度
8.工厂模式的使用。+(UIButton)buttonWithType:(UIButtonType)type;
9.SEL又叫选择器,是表示一个方法的selector的指针,仅仅是是函数的标识.(函数名字hash) -> 整数,查询速度快.
IMP才是函数指针,指向方法实现的首地址.
method维护SEL与IMP的映射关系。
objc_msgSend(receiver, selector),objc_msgSend(receiver, selector, arg1, arg2, ...)
在cache中寻找SEL->在MethodTable寻找SEL。
_objc_msgForward消息转发做的几件事:
消息转发:1.动态方法解析 2.备用接收者 3.完整转发
1. resolveInstanceMethod(resolveClassMethod)+ class_addMethod
2.forwardingTargetForSelector
3.forwardInvocation methodSignatureForSelector 如果函数带返回值,则返回最后一个接收者的处理值
调用methodSignatureForSelector:方法,尝试获得一个方法签名。如果获取不到,则直接调用doesNotRecognizeSelector抛出异常。如果能获取,则返回非nil:创建一个 NSlnvocation 并传给forwardInvocation:。
10.每个对象结构体的首个成员都是Class类的变量(isa),Class结构用于描述对象所属的类。Class对象是单例,每个类的Class仅有一个实例。
isKindOfClass判断对象是否是某类或其派生类;isMemeberOfClass判断对象是否为某个特定类。
11.提供一个(或多个)全能的初始化方法供其他初始化调用,这样在底层结构发生变化时,只需修改全能初始化方法即可。子类可根据实际需求,适时的覆写超类的全能初始化方法。
12.养成加前缀的习惯避免冲突
13.po打印内容对应debugDescription方法
14.如果某个属性对外只读,对内可读可写,则可在扩展中"重写"@property.
15.异常只应应用于极其严重的错误。
可以通过在超类方法里抛出异常的方式,要求子类必须覆写超类方法,模拟实现抽象类的效果。
返回错误时可以借助NSError(domain、code、info)对错误进行描述。
-(BOOL)doSomething:(NSError **)error
if(/*has error*/)
if (error)
*error = [NSError errorWithDomain:domain code:code userInfo:info];
return NO;
else
return YES;
16.NSZone:以前开发程序时,会把内存分成不同的区,而对象会创建在某个区内。而现在每个程序只有一个默认区。
17.对一不可变对象复制,copy是指针复制和mutableCopy是对象复制。如果是对可变对象复制,都是对象复制,但是copy返回的对象是不可变的。但是collection每个元素都是指针复制,如果相对元素也做到对象复制,可借助-(id)initWithSet:(NSArray *)array copyItems:(BOOL)copyItems类似方法。但如果考虑collection内的元素本身是不可变元素,则还存在trueDeepCopyArray的概念。
18.在使用代理时,在每次调用代理方法时,可能会经常频繁判断代理类是否实现了某代理方法,为了避免多余的检测,可以一上来(比如setDelegate时)判断一次,然后将结果通过自定义的数据结构缓存起来,这样就不用每次去responseToSelector了,提高效率。
19.借助类别将代码(类)模块化,还可实现细节隐藏(可见控制)。
借助扩展可以实现方法与属性的私有化,隐藏其遵循的协议等。还可在扩展中"重置"属性在内部的读写特性。
20.勿在类别中声明属性。类别本身基于消息机制,动态修改*methodLists的值来添加方法。如果在类别中声明属性,需要自己实现存取方法,进行关联对象,或是返回一个计算属性。
21.id<协议>,协议本身关心的是方法是否被实现(遵循),而不关心对象本身的类型。
以上是关于《Effective Objective-C 2.0编写高质量iOS与OS X代码的52个有效方法》读书笔记(上)的主要内容,如果未能解决你的问题,请参考以下文章
Effective Objective-C 2.0 — 第14条:理解“类对象“的用意
《Effective Objective-C 2.0》读后总结 之五
《Effective Objective-C 2.0》读后总结 之四
《Effective Objective-C 2.0》读后总结 之三