美文网首页
【iOS】Runtime相关

【iOS】Runtime相关

作者: an_Anthony | 来源:发表于2019-04-27 22:38 被阅读0次

    什么是Runtime(运行时)

    Runtime是用来将面向对象的Objective-C转换成面向过程的C的一套纯C语言API,有了Runtime可以将数据类型的确定由编译时推迟到运行时。

    在Runtime中类和对象如何表示

    在runtime中,Objective-C的类是由Class类型来表示的。在objc.h中可以看到Class类型实际上是指向结构体objc_class的指针。在这个结构体中有几个重要的字段:

    isa:在Objective-C中所有的类自身也是一个对象。对象需要isa指针来找到它的类,类需要isa指针来找到它的元类。任何NSObject继承下的元类都有isa指针指向它的元类,而NSObject的isa指针指向NSObject元类。

    super_class:指向该类的父类,如果该类是最顶层的类,super_class为nil

    cache:用来缓存类中最近使用的方法

    ivars:指向该类成员变量链表

    methodLists:指向方法定义的链表

    protocols:指向协议链表

    如何使用Runtime动态添加一个类

    使用runtime动态创建一个类或对象需要用到三个函数:

    objc_allocateClassPair(<#Class  _Nullable __unsafe_unretained superclass#>, <#const char * _Nonnull name#>, <#size_t extraBytes#>):创建一个新类或者元类。要想使其成为基类必须将super_class置为nil。参数extraBytes是分配给类和元类对象尾部索引ivars的字节数,通常为0

    objc_registerClassPair(<#Class  _Nonnull __unsafe_unretained cls#>):创建完新类后需要使用这个函数来注册这个类,之后才能在程序中使用。

    objc_disposeClassPair(<#Class  _Nonnull __unsafe_unretained cls#>):用来销毁该类及其元类,在销毁之前需要将该类的实例全部置为nil。

    如何使用Runtime在类别(Category)中添加属性

    runtime提供关联对象方法,动态地为添加到Category的属性实现getter和setter。

    objc_setAssociatedObject(<#id  _Nonnull object#>, <#const void * _Nonnull key#>, <#id  _Nullable value#>, <#objc_AssociationPolicy policy#>):用来实现setter

    objc_getAssociatedObject(<#id  _Nonnull object#>, <#const void * _Nonnull key#>):用来实现getter

    事实上,关联对象是使用哈希表实现的,将一个类映射到一张哈希表上,然后根据key找到关联对象。

    Runtime和消息传递机制

    消息传递用到的函数是objc_msgSend( id self, SEL op, ...  )。参数self代表消息接受者,SEL表示方法名。每个类的方法列表(methodLists)中的指针都会指向方法的实现,方法名是查询时用到的key。消息传递流程如下:

    objc_msgSend通过isa指针找到接受者所属的类

    在该类的cache和methodLists中通过SEL查找对应的方法,找到就跳转至实现代码IMP

    如果找不到就通过super_class到该类的父类中找

    如果都找不到就执行消息转发机制

    Runtime和消息转发机制

    1、动态补加方法(动态方法解析)

    + (BOOL)resolveInstanceMethod:(SEL)sel

    + (BOOL)resolveClassMethod:(SEL)sel

    这两个方法的参数就是未知的方法,返回的是BOOL类型,表示这个类能否动态的添加一个新的方法来处理这条信息。

    2、直接返回消息给另一个对象处理(备用接收者)

    - (id)forwardingTargetForSelector:(SEL)aSelector

    3、手动生成签名方法并抓发给另一个对象(完整的消息转发机制)

    - (NSMethodSignature *)methodSignatureForSelector:(SEL)sSelector

    - (void)forwardInvocation:(NSInvocation *)anInvocation

    Runtime和KVC:暴力访问私有属性和变量

    KVC访问变量不受私有权限的限制。runtime可以使用class_copyIvarList函数获取类对象的Ivar变量列表,可以使用object_getIvar和object_setIvar对变量进行暴力访问。

    Runtime暴力访问对象私有方法

    使用class_copyMethodList来获取类对象的方法列表,使用performSelector执行某个方法。还可以使用class_addMethod往类对象中强行添加新的方法。

    相关文章

      网友评论

          本文标题:【iOS】Runtime相关

          本文链接:https://www.haomeiwen.com/subject/ptxlnqtx.html