首页 > 其他 > 详细

OC之消息调用过程

时间:2015-10-19 23:46:59      阅读:284      评论:0      收藏:0      [点我收藏+]

Bird * aBird = [[Bird alloc] init];

[aBird fly]; 

中对 fly 的调用,编译器通过插入一些代码,将之转换为对方法具体实现 IMP 的调用,这个 IMP 是通过 在 Bird 的类结构中的方法链表中查找名称为 fly 的 选标 SEL 对应的具体方法找到实现的。

那么编译器插入了什么代码?如果在方法链表中没有找到对应的 IMP 又会如何 ?

消息函数 obj_msgSend:
编译器会将消息转换为对消息函数 objc_msgSend 的调用,该函数有两个主要的参数:消息接收者 id 和

消息对应的方法选标 SEL, 同时接收消息中的任意参数: id objc_msgSend(id theReceiver, SELtheSelector, ...)

如上面的消息 [aBird fly]会被转换为如下形式的函数调用: objc_msgSend(aBird, @selector(fly)); 

 

该消息函数做了动态绑定所需要的一切工作:
1,它首先找到 SEL 对应的方法实现 IMP。因为不同的类对同一方法可能会有不同的实现,所以找到的 方法实现依赖于消息接收者的类型。
2, 然后将消息接收者对象(指向消息接收者对象的指针)以及方法中指定的参数传递给方法实现 IMP。 

3, 最后,将方法实现的返回值作为该函数的返回值返回。

 

在方法中可以通过 self 来引用消息接收者对象,通过选标_cmd 来引用方法本身。在下面的例 子中,_cmd 指的是 strange 方法,self 指的收到 strange 消息的对象。 

1 ?
2 - strange {
3     id target = getTheReceiver(); 
4     SEL method = getTheMethod();
5     if (target == self || mothod == _cmd) 
6     return nil;
7     return [target performSelector:method];
8  }
查找 IMP 的过程:

 前面说了,objc_msgSend 会根据方法选标 SEL 在类结构的方法列表中查找方法实现 IMP。这里头有一 些文章,我们在前面的类结构中也看到有一个叫 objc_cache *cache 的成员,这个缓存为??高效率而存在 的。每个类都有一个独立的缓存,同时包括继承的方法和在该类中定义的方法。

下面来剖析一段苹果官方运行时源码:
 1 static Method look_up_method(Class cls, SEL sel,
 2                              BOOL withCache, BOOL withResolver)
 3 {
 4     Method meth = NULL;
 5     if (withCache) {
 6         meth = _cache_getMethod(cls, sel, &_objc_msgForward_internal);
 7         if (meth == (Method)1) {
 8             // Cache contains forward:: . Stop searching.
 9         return NULL;
10         }
11   }
12     if (!meth) meth = _class_getMethod(cls, sel);
13     if (!meth  &&  withResolver) meth = _class_resolveMethod(cls, sel);
14     return meth;
15 }
通过分析上面的代码,可以看到,查找时:

1,首先去该类的方法 cache 中查找,如果找到了就返回它;

2,如果没有找到,就去该类的方法列表中查找。如果在该类的方法列表中找到了,则将 IMP 返回,并将 它加入 cache 中缓存起来。根据最近使用原则,这个方法再次调用的可能性很大,缓存起来可以节省下次 调用再次查找的开销。3,3,如果在该类的方法列表中没找到对应的 IMP,在通过该类结构中的 super_class 指针在其父类结构的方法列表中去查找,直到在某个父类的方法列表中找到对应的 IMP,返回它,并加入 cache 中;

4,如果在自身以及所有父类的方法列表中都没有找到对应的 IMP,则看是不是可以进行动态方法决议(后 面有专文讲述这个话题);

5,如果动态方法决议没能解决问题,进入下面要讲的消息转发流程。 

 

OC之消息调用过程

原文:http://www.cnblogs.com/H7N9/p/4893323.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!