effective OC2.0 52阅读笔记(二)

第二章:对象、消息、运行期

6 理解属性这一概念

总结:OC解决硬编码偏移量问题的做法,一种方案是把实例变量当做一种存储偏移量所用的特殊变量,交由类对象保管,偏移量会在运行期查找,叫做稳固的“应用程序二进制接口”ABI。二种方案是使用存取方法访问实例变量。属性的访问方法由编译器在编译期执行,并且编译器还会自动向类中添加实例变量。

eg:如果从core data的框架中的NSManagedObject类里继承一个子类,就需要在运行期动态创建存取方法。因为子类的某些属性不是实例变量,其数据来自后端的数据库中。

@interface EOCPerson:NSManagedObject

@property NSString *firstName;

@property NSString *lastName;

@end

@implementation EOCPerson

@dynamic firstName,lastName;//编译器在此时不会自动合成存取方法或实例变量。

@end

属性特质可以分为四类,原子性,读/写权限,内存管理语义(只要实现属性所用的对象是可变的,就应该在设置新属性值时拷贝一份) 方法名@property(nonatomic,getter=isOn) BOOL on;

实现自定义的初始化方法时,一定要遵循属性定义中宣称的“copy”语义,_first = [firstName copy];使用于别的内存管理语义。

注意:不应该在init方法中调用存取方法;应该尽可能使用不可变对象。

7 在对象内部尽量直接访问实例变量

总结:建议在读取实例变量的时候采用直接访问形式,而在设置实例变量的时候通过属性来做。

两种做法区别:直接访问实例变量速度快,编译器所生成的代码会直接访问保存对象实例变量的那块内存。但会绕过为相关属性定义的内存管理语义。不会触发键值观测。通过属性访问有助于排查相关错误。

通过设置方法写入实例变量时需要注意,在初始化方法中及dealloc方法中应该直接访问实例变量,对于初始化方法是因为子类可能会复写设置方法。在基类的默认初始化方法中,可能会将姓氏设为空字符串。此时若是通过设置方法来做,那么调用的将会是子类的设置方法,从而抛出异常。

- (void)setLastName:(NSString *)lastName

{

if(![lastName isEqualToString:@"smith"]){

[NSException raise:NSInvalidArgumentException format:@"Last name must be Smith"];

}

self.lastName = lastName;

}

另外:当要惰性初始化的时候,必须通过获取方法来访问属性,否则,实例变量就永远不会初始化。

8 理解“对象等同性”这一概念

总结:判断等同性的两个关键方法:- (BOOL)isEqual:(id)object; - (NSUInteger)hash;编写hash方法时,应该用当前的对象做做实验,以便在减少碰撞频度与降低运算复杂程度之间取舍。有时候判断等同性可以根据特有的标识符,就像主键一样。放入容器中的对象不应再改变,例如把某个对象放入set之后又修改其内容,那么后面的行为将很难预料。相同的对象必须具有相同的哈希码,但是两个哈希码相同的对象未必相同。不要盲目地逐个检测每条属性,而是应该依照具体需求来制定检测方案。编写hash方法时,应该使用计算速度快而且哈希码碰撞几率低的算法。

9 以类族模式隐藏实现细节

总结:类族模式可以把实现细节隐藏在一套简单的公共接口后面。工厂模式是创建类族的办法之一。Cocoa系统框架中大部分collection类都是类族。例如:用NSArray的alloc方法获取实例时,该方法首先会分配一个属于某类的实例,此实例充当“占位数组”。该数组稍后会转为另一个类的实例,而那个类则是NSArray的实体子类。当向类族中新增实体子类时,对于Employee这个例子来说,若是没有工厂方法的源代码,就无法向其中新增雇员类别了。然而对于NSArray这样的类族来说,还是有办法增加子类的,但是从类族的公共抽象积累中继承子类时要当心,若有开发文档,应先阅读。

10 在既有类中使用关联对象存放自定义数据

总结:有时需要在对象中存放相关信息,但是该类的实例可能是由某种机制所创建的,而我们无法令这种机制创建出自己缩写的子类实例。就要用关联对象(associated object)来解决这个问题。objc_setAssociatedObject(object,void *key,id value,objc_AssociationPolicy),objc_getAssociatedObject(object,key),objc_removeAssociatedObjects(object)。类似于NSDictionary,设置关联对象时用的键是不透明指针(opaque pointer),如果在两个键上调用isEqual方法的返回值是YES,那么NSDictionary就认为而这项等。然后在设置关联对象时,若想令两个键匹配到同一个值,则二者必须是完全相同的指针才行。所以设置关联对象值时,通常使用静态全局变量做键。只有在其他做法不可行时才应选用关联对象,因为这种做法通常会引入难于查找的bug。

11 理解objc_msgSend的作用

总结:边界情况(特殊情况),objc_msgSend_stret返回结构体,objc_msgSend_fpret返回浮点数,objc_msgSendSuper。尾调用优化技术:如果某函数的最后一项操作是调用另外一个函数,而不会将其返回值另作他用时,才能执行“尾调用优化”。只保留内层函数的调用记录,如果所有函数都是尾调用,那么完全可以做到每次执行时,调用记录只有一项,这将大大节省内存。消息由接收者,选择子及参数构成。给某对象发送消息,也就相当于在该对象上调用方法。发给某对象的全部消息都要有动态消息派发系统来处理,该系统会查出对应的方法,并执行其代码。

12 理解消息转发机制

总结:消息转发分为两大阶段,一动态方法解析:先征询接收者,所述的类,看能否添加动态方法;二完整的消息转发机制:先看有没有其他对象能处理这条消息。若没有则启动完整的消息转发机制,运行期系统会把与消息有关的全部细节都封装到NSInvocation对象中。

+ (BOOL)resolveInstanceMethod:(SEL)selector;(尚未实现的是实例方法调用这个方法)

+(BOOL)resolveClassMethod:(SEL)selector;(尚未实现的是类方法)

用+ (BOOL)resolveInstanceMethod:(SEL)selector实现@dynamic属性

return YES;或者是return [super resovleInstanceMethod:selector];动态添加方法

- (id)forwardingTargetForSelector:(SEL)selector;可以模拟出多重继承的某些特性,但是无法操作由这一步所转发的消息。

- (void)forwardInvocation:(NSInvocation*)invocation;一是改变调用目标,但是与上一步效果等效。二是出发消息前,先以某种方式改变消息内容,追加另外一个参数,或是改换选择子。

CALayer是兼容与键值编码的容器类,就是说,能够向里面随意添加属性,然后以键值对的形式来访问。属性值的存储工作由基类直接负责,我们只需在CALayer的子类中定义新属性即可。

若对象无法响应某个选择子,则进入消息转发流程。通过运行期的动态方法解析功能,我们可以在需要用到某个方法时再将其加入类中。对象可以把其无法解读的某些选择子转交给其他对象来处理。经过上述两步之后,如果还是没有办法处理选择子,那就启动完整的消息转发机制。

13 用方法调配技术调试黑盒方法

总结:交换方法用void method_exchangeImplementations(Method m1,Method m2);方法实现用Method class_getInstanceMethod(class aClass,SEL aSelector)。通过此方案,可以为那些完全不知道其具体实现的黑盒方法增加日志记录功能,有助于程序调试。但若滥用,会使代码变得不易读懂且难于维护。

14 理解类对象的用意

总结:在程序中不要直接比较对象所属的类,明智的做法是调用类型信息查询方法,isKindOfClass和isMemberOfClass,也可用比较类对象是否等同的办法来做。若是如此,就要使用==操作符,不要用isEqual,因为类对象是单利,在应用程序范围内,每个类的Class仅有一个实例。每个类仅有一个类对象,所以可以使用==,而每个类对象仅有一个与之相关的元类。尽量使用类型信息查询方法来确定对象类型,而不要直接比较对象,因为某些对象可能实现了消息转发功能,如果用直接比较的方法class返回的对象和查出来的类对象是不同的,class方法所返回的类表示发起代理的对象,而非接受代理的对象。

时间: 2024-10-07 07:04:41

effective OC2.0 52阅读笔记(二)的相关文章

effective OC2.0 52阅读笔记(七 系统框架)

47 熟悉系统框架 总结:将代码封装为动态库,并提供接口的头文件,就是框架.平时的三方应用都用静态库(因为iOS应用程序不允许在其中包含动态库),并不是真正的框架,然而也经常视为框架.例如:NSLinguisticTagger可以解析字符串并找到其中的全部名词.动词.代词等.无缝桥接:将CoreFoundation中的C语言数据结构平滑转换为Foundation中的Objective-C对象,也可反向转换.OC编程一个重要特点是,经常需要使用底层的C语言级API,用C语言来实现API的好处是,可

effective OC2.0 52阅读笔记(五 内存管理)

第五章:内存管理 29 理解引用计数 30 以ARC简化引用计数 总结:ARC通过命名约定将内存管理规则标准化.其他编程语言很少像OC这样强调命名.ARC通过设置全局数据结构(此数据结构的具体内容因处理器而异)中的一个标志位,来代替直接调用autorelease和retain.这是ARC所带来的好处.待编译器与运行期组件日臻成熟,还会出现其他的优化技术.CoreFoundation对象不归ARC管理,开发者必须适时调用CFRetain/CFRelease. 31 在dealloc方法中只释放引用

effective OC2.0 52阅读笔记(六 块与大中枢派发)

派发队列:dispatch_queue 操作队列:NSOperationQueue  组:dispathc_group_t 37 理解“块”这一概念 总结:块就是一个值,且自有其相关类型.块的强大之处是,在声明它的范围里,所有变量都可以为其所捕获,如果捕获的变量是对象类型,就会自动保留.且默认情况下被块所捕获的变量,是不可以在块里修改的,若想修改此变量.声明变量的时候可以加上__block.如果将块定义在了OC类的实例方法里,那么除了可以访问类的所有实例变量之外,还可以使用self变量.块总能修

effective OC2.0 52阅读笔记(六 大中枢派发)+ Objective-C高级编程 (三Grand Central Dispatch)

41 多用派发队列,少用同步锁 总结:当多个线程执行同一份代码时,可能会出现问题,这时有@synchronized(self){}内置同步块.或NSLock对象.然而这只是某种程度上的线程安全,使用串行同步队列(serial sychronization queue).更有效率的方法是使用串行队列同步取方法,异步设置方法.执行异步派发时需要拷贝块.再优化就是改用并发队列,同步取方法,使用栅栏块(只是对并发队列有意义)异步设置方法(读取操作可以并行,但是写入操作必须单独执行)dispatch_ba

effective OC2.0 52阅读笔记(四 协议与分类)

23 通过委托与数据源协议进行对象间通信 总结:委托模式的常规委托模式中,信息从类Class流向受委托者delegate.数据源模式,信息从数据源datasource流向class.数据源和受委托者可以是两个不同对象.有时候一个可选择方法可能在一个生命期中多次调用,如果每次都检查委托对象是否能响应选择子,那就显得多余了.可以使用位段(bitfield)数据类型将方法响应能力缓存起来. 24 将类的实现代码分散到便于管理的数个分类之中 总结:易于管理,便与调试.将应视为“私有”的方法归入名为Pri

《逻辑思维简易入门》(第2版) 阅读笔记二

<逻辑思维简易入门>(第2版) 阅读笔记二 本周阅读的是<逻辑思维简易入门>的第三章,也就是说,本书的第一部分就已经读完了. 第三章.信念的优点 信念和负信念是人们在接受一个事物时一种心理态度,延伸来说也就是对事物的认知态度.因为我们在研究 逻辑思维的时候,都有一个前提:“以正常情况以及说话者真诚”,所以有人如果对于一件事物不做回应,我们可以认为这是一种既不相信,也不怀疑的的态度. 信念的优缺点有很多,在书中主要介绍了下面几种: 1.准确性 好的信念实在准确的表达事实,同样真的信念

寒假阅读笔记二

大型网站技术架构-阅读笔记二 模式:每一个模式描述了一个在我们周围不断发生的问题及该问题解决方案的核心.这样你就能一次又一次地使用该方案而不必做重复工作. 分层:将系统在横向维度上切分成几个部分,每个部分负责一部分相对比较单一的职责,然后通过上层对下层的依赖和调用组成一个完整的系统.分层时必须合理规划层次边界和接口,在开发过程中,严格遵循分层架构的约束,禁止跨层次的调用(应用层直接调用数据层)及你想调用(数据层调用服务层,或者服务层调用运用层). 分割:网站越大,功能越复杂,服务和数据处理的种类

构建之法--阅读笔记二

阅读笔记二—代码规范 代码的风格的原则就是:简明,易读,无二义性.我虽然是计算机系的学生,但是我以前却没有秉着这个原则来编写代码,现在阅读了构建之法后,我明白了如何让你的代码变得简明,更容易理解. 代码在编写的过程中注意: 用Tab键缩进 要注意行宽,最多限定100字符的行宽 在复杂的条件表达式中,用括号清楚地表达逻辑优先级 要注意断行与空白的{ }行,有明确的“{”和“}”来判断程序的结构 不要把过多的语句放在同一行上 对变量命名要有实际的意义 用下划线来分隔变量名字中的作用域标注和变量的语义

【Bootstrap3.0建站笔记二】按钮可下拉弹出层

1.按钮可下拉弹出层: HTML代码: <div class="porpre"> <div class="input-group-btn" style="width: auto"> <a href="CustomerInformationDetails.aspx?Id=7&phone=15821789965&RecommendationNumber=54231896&tabPage=