一图胜千言,习惯性的先来一张图以便对消息转发有个整体的把握
运行时系统库方法查询流程图
对于对象无法处理的消息,如果不做转发处理的话,程序最终会调用NSObjective的doesNotRecognizeSelector:消息将程序crash掉。
Objective-C提供了两种消息转发选项
- 快速转发:NSObject类的子类A可以通过重写NSObject类的forwardingTargetForSelector:方法,将A的实例无法识别的消息转发给目标对象B,从而实现快速转发。该技巧就像是将对象的实现代码与转发对象合并到一起。这类似于实现的多继承行为。如果你有一个定了对象 能够消化哪些消息的目标类,这个技巧可以取得很好的效果
- 标准(完整)转发:NSObject类的子类A可以通过重写NSObject类的forwardInvocation:方法,实现标准转发。标准转发巧可以通过methodSignatureForSelector:方法获取一个methodsignature对象最终被封为NSInvocation对象传递给forwardInvocation:方法(注意如果methodSignatureForSelector:方法返回一个nil,程序会crash)从该对象能获取消息的全部内容(包含目标,方法名,和参数)。
如果你拥有了一个定义了对象能够消化哪些消息的目标类,快速转发可以取得很好的效果。如果你没有这样目标类或想要执行其他处理过程(如记录日志并‘吞下’消息),就应该使用完整转发。
写了一大推字感觉很抽象,下面来点干货
下面我要把Test实例的logName消息转发给Target实例,代码如下
Test头文件
Test实现文件
|
|
目标文件的头文件
目标文件的实现文件
扩展:简单说一下NULL,nil,Nil,NSNull的用处
NULL:用于普通类型,例如NSInteger
nil:用于OC对象(除了类这个对象),给nil对象发送消息不会crash
Nil:用于Class类型对象的赋值(类是元类的实例,也是对象)
NSNull:用于OC对象的站位,一般会作为集合中的占位元素,给NSNull对象发送消息会crash的,后台给我们返回的