runtime总结

前段时间看了一些有关Runtime的东西,为了加深自己的理解,我想是时候写一波总结了:

我们常说oc是运行时语言,而c是静态语言,为什么呢?这是因为在c中调用某个函数,在编译时就可以知道。但是在oc中调用某个函数,在编译时是不能确定的,甚至oc可以调用某个只声明确没有实现的方法,编译时完全不会报错。因为oc调用方法是通过发送消息的机制获取方法的,它把确定调用的方法放到运行时进行处理。

当oc对象调用某个方法,如:[obc getVar],实际在底层调用的是obc_msgSend(obc,@selector(getVar),......)这个函数,后面的........表示这个方法的参数。那这个函数怎么找到方法的地址呢?

oc中每个东西包括对象,类型,协议在底层c代码其实都是结构体。而对象如obc这个结构体具体如下:


在这个结构体中,我们主要注意以下几个参数,isa

这个参数是指指向元类型的,什么是元类型呢?通俗点说,就是对象的指向普通Class,普通Class主要保存了一些实例方法(-)号的方法,而普通的Class指向静态的Class,静态的Class保存一些类方法(+)号的方法。

参数,super_class这个参数主要指向它的父类型

参数,ivars这个参数主要指向它的属性的地址

参数, methodLists,这个参数主要保存它里面的一些方法

参数,cache,这个参数主要保存它最近使用的方法

参数,protocols,这个参数主要保存它使用了哪些协议

好了,这个结构体就说这么多,下面说说@selector

这个是一个SEL类型,SEL类型其实就是方法名字,有了方法名字就可以在上述结构体中找到相应方法的入口地址,由于oc是通过方法名作为key,故而不想C++那样可以有同名的方法,即使参数类型不同。

而与SEL相对应的是一个IMP的指针,他指向的是方法的实现。methodLists保存了SEL到IMP的映射。

oc调用某个函数的过程其实是这样:[obc,getVar]-->obc_msgSend(obc,@selector)-->然后obc_msgSend这个函数首先在上述结构体查找cache是否有改方法,如果没有,就到methodLists中根据名字查找方法的入口地址,没找到,就到super_class重复上述过程,最后如果找到,就把方法保存在cache中,没找到,就触发消息转化机制。至于消息转化机制,主要包括3种:1,动态方法解析。2,快速转发。3,完整转发。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值