runtime和动态绑定

我们都知道OC是动态语言,表现为对象方法的调用实际上是对对象发送消息,编译时不确定这个对象执行什么方法,而在运行时由消息(方法选择器selector决定对象执行什么方法),这种消息发送的方式叫做动态绑定

oc是一门动态语言,它允许操作在运行的时候才执行

oc的这种特性是基于runtime实现的,runtime底层是由c语言编写,oc编写的代码在执行的时候最终都会转化成runtime api进行运行。

oc的消息转发机制

在调用对象的方法的时候,编译器会转化为objc_msgSend(obj, @selector (makeText));通过对象的isa指针去对象的class中查找对应的方法去执行,分为以下几步

  1. 获取传入对象所属的类。
  2. 使用传入的selector在缓存cache列表中查询。
  3. 如果找到了方法,则通过Method中的IMP(方法实现的地址)去调用方法。
  4. 如果缓存中不存在,则开始在methodLists列表中查找。
  5. 如果methodLists列表找不到,利用super_class指针去父类查找,
  6. 递归地查找父类,一直查找到NSObject,如果还是找不到,则触发消息转发机制。

如果当前类和父类中都没有找到对应的方法,执行一下几步操作

1⃣️动态方法解析 

动态方法解析:向当前类发送 resolveInstanceMethod: 信号,检查是否动态向该类添加了方法。

2⃣️尝试快速消息转发

检查该类是否实现了 forwardingTargetForSelector: 方法,若实现了则调用这个方法。若该方法返回值对象非nil或非self,则向该返回对象重新发送消息

3⃣️尝试标准消息转发

runtime发送methodSignatureForSelector:消息获取Selector对应的方法签名。返回值非空则通过forwardInvocation:转发消息,返回值为空则向当前对象发送doesNotRecognizeSelector:消息,程序崩溃退出

4⃣️抛出异常

@property有两个对应的词,一个是@synthesize,一个是@dynamic。如果@synthesize和@dynamic都没写,那么默认的就是@syntheszie var = _var;
@synthesize的语义是如果你没有手动实现setter方法和getter方法,那么编译器会自动为你加上这两个方法
@dynamic告诉编译器:属性的setter与getter方法由用户自己实现,不自动生成(当然对于readonly的属性只需提供getter即可)
假如一个属性被声明为@dynamic var,然后你没有提供@setter方法和@getter方法,编译的时候没问题,但是当程序运行到instance.var = someVar,由于缺setter方法会导致程序崩溃;或者当运行到 someVar = instance.var时,由于缺getter方法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所谓的动态绑定


 

上一篇:Pinia 快速入门


下一篇:lombook插件使用