iOS Runtime修炼<二>

基情四射的日子

我总是对神秘的事物产生兴趣,自从知道了Objective-C的Runtime技能,我便试着接近它,讨好它,因为只有对这个技能了如指掌,我才能征服它,才能在修仙的道路上顺利前进。


消息传递函数: objc_msgSend

这个可以说是Runtime系统的根基,因为所有的OC方法调用最终都会转换成objc_msgSend函数的调用。这么重要的秘密,没想到只给丫喝了两瓶啤的,它就告诉了我。看来酒量不行,难在江湖混呐。

招式破解:[receiver message] ----> objc_msgSend(receiver, selector, arg1, arg2, ...)     objc_msgSend在执行的过程中,会悄悄的传入接收对象和方法选择器这两个参数。

看了Runtime醉酒的样子,我心里嘀咕着:“就这货,怎么能有这么强大的力量?”果然不出我所料,这货有一枚神器叫编译器,一直在默默的帮助着它。就这个消息传递,也是因为编译器为每一个类和对象构建了各自的结构,才能使其顺利施放技能。那我倒是要看看,这个类结构到底是啥?

类结构破解:    

类结构包含了一个指向父类的指针(isa)和一个类调度表。类调度表记录了类中选择器对应的具体内存地址,就像这样:selector ----> address 。当调用一个方法,也就是给对象发送一个消息的时候,会根据isa找到类结构,并在调度表中查找匹配的selector;如果不能匹配,objc_msgSend就根据isa到父类类结构里与调度表中的selector匹配,依此类推直到NSObject类。一旦匹配到了selector,就调用表中记录的函数(address),否则将启动消息转发机制。这种在运行时选择方法实现的过程称为动态绑定。

强大的Runtime必然会有很多的招式,这招动态绑定,我给90分。因为我觉着这样灵活的招式,肯定会有它的弊端。首先在编译期不能确定方法的位置,这就给运行时造成了不可避免的麻烦,从而导致效率上的问题。哼哼~果然被我找到了弱点。但是后来的一番话,差点迷惑了我。

效率提升招式之缓存: 

每个类都有单独的缓存,包含了继承的selector和类中定义的selector(只有在曾今调用过的方法才会进行缓存)。在匹配调度表之前,先检查接收对象的类缓存(哈希散列算法),如果缓存中有匹配的selector,就直接使用。这大大减少了运行时查询selector所消耗的时间。

我差点就信了。后来仔细一想,如果我连续多次调用一个特定的方法,那不就玩完了吗?哈哈哈,丫果然有弱点,看我怎么支配你。

我也算是武学奇才,一会儿就研究了一个招式:规避动态绑定机制。

首先我要想办法得到一个方法的内存地址,然后就直接调用啊,这不就没有查找selector的过程了吗。至于怎么得到方法的地址,就要靠methodForSelector方法了。请看下面的招式玩耍:

void (*showTitle)(id, SEL, NSString *);

int i;

showTitle = (void(*)(id, SEL, NSString *))[target methodForSelector:@selector(showMessage:)];

for (i=0; i<1000; ++i) {

    showTitle(targetList[i], @selector(showMessage:), "邪魔退散");

}

这样在重复多次调用一个特定的方法,有显著的效率提升。

学会了这招技能,我看着熟睡的Runtime,心想:“总有一天,在你遇到问题的时候,我会助你一臂之力的。”

不会吧,我竟然对它没有了敌意。看来在修仙的道路上,我会多一位兄弟(jiyou)了。




关注微信公众号CodingArtist,可以第一时间得到文章更新通知!  ^_^

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 转至元数据结尾创建: 董潇伟,最新修改于: 十二月 23, 2016 转至元数据起始第一章:isa和Class一....
    40c0490e5268阅读 5,802评论 0 9
  • objc_getAssociatedObject返回与给定键的特定对象关联的值。ID objc_getAssoci...
    有一种再见叫青春阅读 5,568评论 0 7
  • 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的转载 这篇文章完全是基于南峰子老师博客的...
    西木阅读 30,702评论 33 466
  • 对于从事 iOS 开发人员来说,所有的人都会答出【runtime 是运行时】什么情况下用runtime?大部分人能...
    梦夜繁星阅读 9,082评论 7 64
  • iOS出身, 一直在开发iOS, 近期公司不做app开发了, 再做VR,游戏之类的开发, 公司缺后台, 所以自己打...
    o0寳贝阅读 2,695评论 0 1