美文网首页
iOS RunTime

iOS RunTime

作者: All_Be_Alright | 来源:发表于2021-10-06 10:02 被阅读0次

    Runtime

    一、数据结构

    基础数据结构

    1、objc_object

    id = objc_object : isa_t为共用体

    objc_objcet

    2、objc_class

    Class = objc_class: Class也是对象,称之为类对象,因为它继承自onjc_object

    objc_class

    3、isa_t

    有两种类型,指针型isa、非指针型isa

    isa_t isa指向

    4、cach_t

    cach_t cache_t

    5、class_data_bits_t

    class_data_bits_t

    6、class_rw_t

    例如分类1中添加的方法会在methods二维数组中的某个数组中存储

    class_rw_t

    7、class_ro_t

    name:类名,可以通过NSClassFromString(name)获取该类

    ivars:成员变量

    properties:属性

    class_ro_t

    8、method_t

    Const char* types: 函数的返回和参数的组合

    method_t

    9、Type Encodings

    第一个参数@代表一个对象,第一个参数和第二个参数是固定的,@代表的是谁调用的,也就是self,第二个:表达的是方法选择器

    Type Encodings

    10、对象、类对象、元类对象

    对象、类对象、元类对象

    Root class指的就是NSObject

    如果一个实例方法在元类对象以及根元类对象中都没有,会查找根类对象中的同名实例方法,并调用。

    指向

    问题

    [self class];

    [super class];

    [self class] [super class]

    二、消息传递

    消息传递

    1、缓存查找

    哈希查找

    哈希查找

    2、在类对象中查找

    类查找

    3、父类逐级查找

    父类逐级查找

    4、消息转发

    消息转发

    a、动态解析

    我们可以根据方法类型(实例方法or类方法)重写一下方法,为类动态添加方法

    +(BOOL)resolveInstanceMethod:(SEL)sel

    +(BOOL)resolveClassMethod:(SEL)sel

    在方法中调用一下方法来动态添加方法的实现

    ** 参数1:给哪个类添加

    ** 参数2:给哪个方法添加

    ** 参数3:方法的实现地址

    ** 参数4:方法的编码类型

    BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

    动态解析 动态解析

    b、消息转发

    消息转发分为两步进行: Fast forwarding和 Normal forwarding

    1> Fast forwarding : 将消息转发给一个其他的OC对象(找一个备用接收者)

    重写以下方法,返回一个其他对象即可

    +/- (id)forwardingTargetForSelector:(SEL)aSelector

    Fast forwarding

    2> Normal forwarding : 实现一个完整的消息转发过程

    如果Fast forwarding没有解决可以重写以下两个方法启动完整的消息的转发

    +/- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector

    Runtime 会根据这个方法签名,创建一个NSInvocation对象(NSInvocation封装了未知消息的全部内容,

    包括:方法调用者 target、方法名 selector、方法参数 argument 等),

    然后调用第二个方法并将该NSInvocation对象作为参数传入。

    +/- (void)forwardInvocation:(NSInvocation *)invocation

    在该方法中:将未知消息转发给其它对象;改变未知消息的内容(如方法名、方法参数)再转发给其它对象;甚至可以定义任何逻辑。

    Normal forwarding

    ⚠️如果第一个方法中没有返回方法签名,或者我们没有重写第二个方法,系统就会认为我们彻底不想处理这个消息了,

    这时候就会调用以下方法

    +/- (void)doesNotRecognizeSelector:(SEL)sel

    方法并抛出经典的 crash:unrecognized selector sent to instance/class,结束 objc_msgSend 的全部流程。

    相关文章

      网友评论

          本文标题:iOS RunTime

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