学计算机的那个

不是我觉到、悟到,你给不了我,给了也拿不住;只有我觉到、悟到,才有可能做到,能做到的才是我的.

0%

消息发送和转发

消息发送(Messaging)是 Runtime 通过 selector 快速查找 IMP 的过程,有了函数指针就可以执行对应的方法实现;

消息转发(Message Forwarding)是在查找 IMP 失败后执行一系列转发流程的慢速通道,如果不作转发处理,则会打日志和抛出异常

函数

函数的四要素

  1. 名称 SEL name
  2. 返回值 const char* types
  3. 参数 const char* types
  4. 函数体 IMP

SEL

SEL是selector在Objc中的表示类型,selector是方法选择器,可以理解为区分方法的 ID,而这个 ID 的数据结构是SEL:

typedef struct objc_selector *SEL;

IMP

IMP在objc.h中的定义是:

typedef void (*IMP)(void /* id, SEL, ... */ );

它就是一个函数指针,这是由编译器生成的。当你发起一个 ObjC 消息之后,最终它会执行的那段代码,就是由这个函数指针指定的。而 IMP 这个函数指针就指向了这个方法的实现。

objc_msgSend

伪代码如下或类似的逻辑,反正就是获取 IMP 并调用

1
2
3
4
5
id objc_msgSend(id self, SEL _cmd, ...) {
Class class = object_getClass(self);
IMP imp = class_getMethodImplementation(class, _cmd);
return imp ? imp(self, _cmd, ...) : 0;
}

self 和 super

看一个问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@interface Phone:Mobile
@end

@implementation Phone

-(id)init
{
self=[super init];
if(self)
{
NSLog(@"%@",NSStringFromClass([self class]));
NSLog(@"%@",NSStringFromClass([super class]));
}
retrurn self;
}

@end

结果是都打印出来 Phone。

来看一下[self class],[super class]的消息传递

这里可以看到 objc_super 结构体当中 receiver 就是当前对象 。 也就是说 无论是 [self class]或者 [super class] ,接收者都是当前对象!

解析
当前的实例是 phone
[self class] –>objc_msgSend(self,@selector(class)), 首先通过实例的 isa 指针找到 phone 的类对象,它本身是没有 class 方法的,然后往父类找,也没有。 顺次一直查找到根类也就是 NSObject ,将 class的具体实现返回给调用方,也就是 phone

1
instance of Subclass --> Subclass(class) -->Superclass(class)-->Root class(class)

[super class] –>objc_msgSendSuper(self,@selector(class))。 接受者依然是当前的 phone 这个实例,区别不同的是 它会从父类的方法了列表开始查找,也就是

1
instance of Subclass --> Superclass(class)-->Root class(class)

所以依然还是 phone;

消息转发

文章参考

  1. Objective-C 消息发送与转发机制原理