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

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方法所返回的类表示发起代理的对象,而非接受代理的对象。

effective OC2.0 52阅读笔记(二 对象、消息、运行期)的更多相关文章

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

    47 熟悉系统框架 总结:将代码封装为动态库,并提供接口的头文件,就是框架.平时的三方应用都用静态库(因为iOS应用程序不允许在其中包含动态库),并不是真正的框架,然而也经常视为框架.例如:NSLin ...

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

    第五章:内存管理 29 理解引用计数 30 以ARC简化引用计数 总结:ARC通过命名约定将内存管理规则标准化.其他编程语言很少像OC这样强调命名.ARC通过设置全局数据结构(此数据结构的具体内容因处 ...

  3. effective OC2.0 52阅读笔记(一 熟悉Objective-C)

    第一章:熟悉Objective-C 1 了解objective-c语言的起源 总结:OC为C语言添加了面向对象的特性,是其超集.采用动态绑定的消息结构而非函数调用,也就是说,要在运行时才检查对象类型及 ...

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

    派发队列:dispatch_queue 操作队列:NSOperationQueue  组:dispathc_group_t 37 理解“块”这一概念 总结:块就是一个值,且自有其相关类型.块的强大之处 ...

  5. effective OC2.0 52阅读笔记(三 接口与API设计)

    第三章:接口与API设计 15 用前缀避免命名空间冲突 总结:避免重名符号错误的唯一办法是变相实现命名空间.为所有符号都加上命名前缀.类和分类都应加三字前缀.注意类实现文件中的纯C函数及全局变量,是算 ...

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

    23 通过委托与数据源协议进行对象间通信 总结:委托模式的常规委托模式中,信息从类Class流向受委托者delegate.数据源模式,信息从数据源datasource流向class.数据源和受委托者可 ...

  7. iOS 52个技巧学习心得笔记 第二章 对象 , 消息, 运行期

    1. 属性 在开发过程中经常要用到定义属性,@property和@synthesize是经常用到的属性, property在.h文件中作声明,@synthesize在.m文件中用于实现 // Stud ...

  8. 《Java编程思想》阅读笔记二

    Java编程思想 这是一个通过对<Java编程思想>(Think in java)进行阅读同时对java内容查漏补缺的系列.一些基础的知识不会被罗列出来,这里只会列出一些程序员经常会忽略或 ...

  9. Java Jdk1.8 HashMap源代码阅读笔记二

    三.源代码阅读 3.元素包括containsKey(Object key) /** * Returns <tt>true</tt> if this map contains a ...

随机推荐

  1. QQ空间HD(2)-UIPopoverController其它使用

    DJTestViewController.m #import "DJTestViewController.h" #import "DJColorTableViewCont ...

  2. webapi支持跨域访问

    写在前面 在实际应用中,跨域请求还是比较常见的,如何上接口直接支持跨域的访问呢? demo 场景项目A有个接口用来获取用户列表,现在项目b也有个功能需要加载用户列表.这两个项目在两个域名下,至少端口好 ...

  3. vim 树形目录插件NERDTree安装及简单用法

    转自: http://blog.csdn.net/love__coder/article/details/6659103 1,安装NERDTree插件 先下载,官网:http://www.vim.or ...

  4. 如何判断retina,如何判断设备的比例

    http://www.189works.com/article-95647-1.html 说起iPhone 4带来的革新,retina display绝对是最吸引眼球的一项,以至于我现在看电脑的显示屏 ...

  5. js反序列化时间

    var time = "/Date(1279270720000+0800)/"; var tme1 = ChangeDateFormat(time); alert(tme1); J ...

  6. ionic导航之后返回功能的说明

    当我导航view之后,再使用$location.path("/path/origin")方法重新定位到初始页面,在深入进入其他的view之后使用这个方法就遇到了问题. 假设这个设置 ...

  7. 【PHP面向对象(OOP)编程入门教程】12.重载新的方法(parent::)

    在学习PHP 这种语言中你会发现, PHP中的方法是不能重载的, 所谓的方法重载就是定义相同的方法名,通过“参数的个数“不同或“参数的类型“不 同,来访问我们的相同方法名的不同方法.但是因为PHP是弱 ...

  8. NFS工作原理及配置文件详解

    nfs工作原理流程       如上图所示,当访问程序通过NFS客户端向NFS服务端存取文件时,其请求数据流程如下几点:     1.首先用户访问网站程序,由程序在NFS客户端上发出NFS文件存取功能 ...

  9. Promise 原理探究及其简单实现

    可移步 http://donglegend.com/2016/09/11/promise%E5%8E%9F%E7%90%86%E6%8E%A2%E7%A9%B6/ 观看 Promise是个什么玩意,大 ...

  10. css3 github javascript

    欢迎关注我的 github github博客地址 github地址