美文网首页
runtime---实例对象、类对象与元类对象&消息传递&消息转

runtime---实例对象、类对象与元类对象&消息传递&消息转

作者: 滨滨_57b5 | 来源:发表于2018-12-24 14:26 被阅读0次

类对象与元类对象的区别和联系

  • 类对象存储的是实例方法列表,元类对象存储的是类方法列表
  • 实例对象是objc_object结构,其中的isa指针指向其类对象,类对象是objc_class结构,objc_class是继承自objc_object结构,因此也有isa指针,其isa指针指向其元类对象,从而可以访问类方法
  • 类对象和元类对象都是objc_class数据结构的
  • 元类对象的isa指针都指向根元类对象,包括根元类对象自身
  • 根元类对象的superclass指针,指向的是根类对象
  • 根类对象的superclass指针,指向nil

当调用的类方法没有时,但是有同名的实例方法存在,那么会不会导致崩溃?

  • 不会崩溃,当调用类方法时,会依次调用元类对象中的类方法列表,直至找到根元类对象的类方法列表,但是仍然没有找到时,会根据元类对象的superclass指针指向的根类对象的方法列表中去找同名的实例方法列表

消息传递流程


NS_ASSUME_NONNULL_BEGIN

@interface Mobile : NSObject

@end

NS_ASSUME_NONNULL_END


#import "Mobile.h"

@implementation Mobile

@end
#import "Mobile.h"

NS_ASSUME_NONNULL_BEGIN

@interface Phone : Mobile

@end

NS_ASSUME_NONNULL_END

#import "Phone.h"

@implementation Phone
- (instancetype)init {
    self = [super init];
    if (self) {
        NSLog(@"%@",NSStringFromClass([self class])); //self isa指向类对象Phone ->NSObject类对象方法列表
        NSLog(@"%@",NSStringFromClass([super class])); //super isa指向类对象
    }
    return self;
}
@end

  • [self class]根据phone实例的isa指针,找到类对象,在类对象的缓存方法列表或实例方法列表中去寻找class这个方法
  • 本身是没有的,然后通过类对象中的superclass指针向其父类mobile中去寻找方法
  • mobile类中也是没有的,顺次查到,直至知道根类对象NSObject,有该方法的实现,调用这个方法的实现,最终返回给接收者receiver,即phone实例对象,打印结果为:Phone
  • [super class]会调用msgsendSuper这个函数,会从Phone类的父类对象方法列表中去查找,其中第一个固定参数是结构体objc_super,该结构体中有一个 id receiver成员,接收者仍然是Phone的实例对象,因此最终打印结果也为:Phone
消息传递流程图.png

消息传递--缓存查找流程

  • 通过给定的方法选择器SEL,作为key,通过hash算法,及通过一个hash函数cache_key_t来获取到对应的bucket_t结构在cache_t中的位置索引,从而获取到bucket_t,最终获取到bucket_t中的IMP函数指针
    f(key) = key & mask

消息传递--当前类对象中的查找流程

  • 在当前类对象的方法列表中,对于已排序好的列表,采用二分查找算法查找方法对应执行函数
  • 对于没有排序好的列表,采用一般遍历查找方法对应执行函数

消息传递--父类逐级查找流程

  • 通过当前类对象的superclass指针逐级向父类查找,判断父类是否为空,如果为空则结束

消息转发流程

  • 对于实例方法的转发流程


    消息转发流程.png
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface RuntimeObject : NSObject

- (void)test;

@end

NS_ASSUME_NONNULL_END


#import "RuntimeObject.h"

@implementation RuntimeObject

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(test)) {
        return NO;
    }else {
        return [super resolveInstanceMethod:sel];
    }
}

- (id)forwardingTargetForSelector:(SEL)aSelector {
    return nil;
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    
    if (aSelector == @selector(test)) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }else {
        return [super methodSignatureForSelector:aSelector];
    }
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    
}
@end

相关文章

  • runtime---实例对象、类对象与元类对象&消息传递&消息转

    类对象与元类对象的区别和联系 类对象存储的是实例方法列表,元类对象存储的是类方法列表 实例对象是objc_obje...

  • Runtime之类对象、元类对象、消息传递

    类对象与元类对象的关系 类对象存储实例方法列表等信息。 元类对象存储类方法列表等信息。 消息传递 消息传递机制 缓...

  • iOS面试之Runtime大全

    Runtime内容如下: 数据结构 类对象与元类对象 消息传递 方法缓存 消息转发 Method-Swizzlin...

  • iOS面试之Runtime模块

    Runtime内容如下: 数据结构 类对象与元类对象 消息传递 方法缓存 消息转发 Method-Swizzlin...

  • Runtime相关

    Runtime 数据结构 类对象与元类对象 消息传递 方法缓存 消息转发 Method-Swizzling 动态添...

  • 对象、类对象、元类对象&消息传递机制

    类对象:存储实例方法列表等信息。 元类对象:存储类方法列表等信息。 调用的类方法没有对应的实现,则会调用同名的实例...

  • #Runtime

    包括以下内容 数据结构 类对象与元类对象 消息传递 方法缓存 消息转发 Method-Swizzling 动态添加...

  • iOS复习之RunTime

    1. 对象、类对象、元类对象2. 消息传递机制3. 消息转发流程4. Method Swizzling (交换方法...

  • [iOS面试]第3章 RunTime相关面试问题

    本文主讲RunTime相关面试问题,包括数据结构、类对象与元类对象、消息传递、方法缓存、消息转发、Method-S...

  • 运行时系统的结构

    编译器 运行时系统组成部分:类元素(接口,实现代码,协议,分类,方法,属性,实例变量)类实例(对象)对象消息传递(...

网友评论

      本文标题:runtime---实例对象、类对象与元类对象&消息传递&消息转

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