iOS Sharing #01 | 2019-03-23

目录

一、Runtime存在的意义是什么?

二、根元类的isa指针指向谁?

三、根元类的superClass指针指向谁?

四、函数四要素都是什么?

五、实例方法去哪里找?


一、Runtime存在的意义是什么?

答:Objective-C 是一门动态语言,它会将一些工做放在代码运行时才处理而并不是编译时。也就是说,有不少类和成员变量在咱们编译的时是不知道的,而在运行时,咱们所编写的代码会转换成完整的肯定的代码运行。所以,只有编译器是不够的,咱们还须要一个运行时系统(Runtime system)来处理编译后的代码。 这就是 Objective-C Runtime 系统存在的意义,它是整个Objc运行框架的一块基石。

平时编写的OC代码,底层都是由他实现的,如:git

[receiver message];
//底层运行时会被编译器转化为:
objc_msgSend(receiver, selector)
//若是其还有参数好比:
[receiver message:(id)arg...];
//底层运行时会被编译器转化为:
objc_msgSend(receiver, selector, arg1, arg2, ...)

复制代码

二、根元类的isa指针指向谁?

答: 见下一问

三、根元类的superClass指针指向谁?

答:这两题一块儿回答。首先看下图:

nsobject

先说几个概念:
1)supercalss : 父类
2)subclass: 子类
3)isa : 概念很差说,官方文档说的也不清晰。做用是根据 isa 指针就能够找到对象所属的类,可是isa指针在代码运行时并不总指向实例对象所属的类型,因此不能依靠它来肯定类型,要想肯定类型仍是须要用对象的 -class 方法。(PS:KVO 的实现机理就是将被观察对象的isa指针指向一个中间类而不是真实类型。)
4)class : 类,一个运行时类中关联了它的父类指针、类名、成员变量、方法、缓存以及附属的协议。(一个实例对象是一个类的实例)
5)meta class :元类,Objc 类自己也是一个对象 ,类对象所属的类就叫作元类(一个类是元类的实例)
github

第一列是类的实例变量,如:[Person new]或者[[Person alloc] init]出来的对象;
第二列是类自己,存放父类指针、类名、成员变量、方法、缓存以及附属的协议的信息;
第三列是元类
缓存

  • 1)isa路线:
    • 实例对象的isa指向Class
    • Class的isa指向Meta Class
    • Meta Class的isa指向根元类Root Meta Class
    • 根元类的isa指向本身
  • 2)superclass路线:
    • 实例对象没有superclass ;
    • 实例对象所在的类,存在superclass,类的superclass后面会指向Root Class,Root Class的super Class是nil;
    • 元类也存在superclass,元类的superclass后面会指向Root Meta Class,而Root Meta Class的superclass倒是Root Class。

因此:数据结构

  • 根元类的isa指针指向本身
  • 根元类的superclass指向root class
  • 根类的isa指向根元类
  • 根类的superclass指向nil

附旧版Class结构:app

typedef struct objc_class *Class;
Class 实际上是指向 objc_class 结构体的指针。objc_class 的数据结构以下:
struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;

复制代码
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
/// A pointer to an instance of a class.
typedef struct objc_object *id;

复制代码
  • Class是一个指向objc_class(类)结构体的指针,而id是一个指向objc_object(对象)结构体的指针。框架

  • objec_object(对象)中isa指针指向的类结构称为objec_class(该对象的类),其中存放着普通成员变量与对象方法 (“-”开头的方法)。函数

  • objec_class(类)中isa指针指向的类结构称为metaclass(该类的元类),其中存放着static类型的成员变量与static类型的方法 (“+”开头的方法)。spa

附图:
旧版Class 3d

objc-old
新版Class

objc-new


四、函数四要素都是什么?

答:函数名,函数参数,参数类型,返回值类型(PS:ObjC通常叫方法,不叫函数)

OC method简单介绍

typedef struct objc_method *Method;
struct objc_method {
    SEL method_name OBJC2_UNAVAILABLE;  //方法名
    char *method_types OBJC2_UNAVAILABLE;   //方法类型
    IMP method_imp OBJC2_UNAVAILABLE;   //方法实现
}
复制代码

objc_method 存储了方法名,方法类型和方法实现。指针

方法名类型为 SEL

方法类型 method_types 是个 char 指针,存储方法的参数类型和返回值类型 method_imp 指向了方法的实现,本质是一个函数指针 Ivar Ivar 是表示成员变量的类型。

typedef struct objc_ivar *Ivar;
struct objc_ivar {
    char *ivar_name OBJC2_UNAVAILABLE;
    char *ivar_type OBJC2_UNAVAILABLE;
    int ivar_offset OBJC2_UNAVAILABLE;
#ifdef __LP64__
    int space OBJC2_UNAVAILABLE;
#endif
}
复制代码

其中 ivar_offset 是基地址偏移字节

IMP

IMP在objc.h中的定义是:

typedef id (*IMP)(id, SEL, ...);
复制代码

它就是一个函数指针,这是由编译器生成的。当你发起一个 ObjC 消息以后,最终它会执行的那段代码,就是由这个函数指针指定的,而 IMP 这个函数指针就指向了这个方法的实现。


五、实例方法去哪里找?

答:其所属的类的方法表

拓展

问:oc是如何找到须要执行哪一个方法的?
答:当须要执行某个实例方法的时候(类方法相似),oc会先去该类的方法的缓存列表里面查找,若找到了,则执行,不然,去该类的方法列表中查找是否存在该方法,存在,执行该方法并更新方法缓存列表,不然,去该父类缓存以及父类方法列表查找,直到根类,若还未找到,则启用动态解析以及消息转发流程,若仍是失败,报unrecognized selector异常

详细流程
感谢大佬提供的流程图


仓库

本篇相关代码


联系方式

邮箱: adrenine@163.com

邮箱: holaux@gmail.com

邮箱: ledahapple@icloud.com

相关文章
相关标签/搜索