runtime事件传递之super的手动内部实现
OC的事件传递会从子类开始寻址,如果没有找到事件,则向它的父类找,还没找到,则会向父类的父类找,一直找到NSObject.
而众所周知,调用父类方法需要用到super关键字.当我们知道的一个对象包含有一个私有方法时,如果需要改写它的私有方法,那么我们就需要调用到父类的方法super关键字.但是此时调用super,Xcode会发脾气啦~"父类找不到这个方法!"
此时如果我们想调用父类的方法就需要一定手段啦!
进入头文件#import <objc/message.h>查看,平时用到的函数
id objc_msgSend(id self, SEL op, ...)
下方有另外一个函数
id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
那么线索来了,这个函数该怎么用呢?
平日里我们都是用的self,此时多出一个结构体struct objc_super *super
点进去发现,原来结构体是这样介绍的:
struct objc_super {
/// 指定一个现有的对象.
__unsafe_unretained id receiver;
/// 指定上面的对象的父类.
#if !defined(__cplusplus) && !__OBJC2__ //如果未定义OC2.0和C++,则定义它
/* 旧款的runtime,我们可以忽略不计 */
__unsafe_unretained Class class;
#else
//新款的class,需要赋值该对象的父类
__unsafe_unretained Class super_class;
#endif
/* super_class is the first class to search */
};
好了,那么我们就开始手动将super关键字实现一下吧!当想手动调用UIViewController的super时需要以下几步:
//定义一个结构体
struct objc_super superclass = {self,self.superclass};
此时,superclass就是我们想要的啦!
如果我们想调用[super viewDidLoad]呢?
代码如下:
((void(*)(struct objc_super *,SEL))objc_msgSendSuper)(&superclass,@selector(viewDidLoad));
*号使用取地址符号即可
那么带参数呢?继续强转向后面拼接参数就可以啦~
------------------------------我 是 有 底 线 的------------------------------