Runtime介绍html
Objective-C语言是一门动态语言,它将不少静态语言在编译和连接时期作的事放到了运行时来处理。这意味着它不只须要一个编译器,也须要一个运行时系统来动态得建立类和对象、进行消息传递和转发。这个运行时系统即Objc Runtime。Objc Runtime实际上是一个Runtime库,它基本上是用C和汇编写的,这个库使得C语言有了面向对象的能力。数组
Runtime库主要作下面几件事:缓存
封装
:在这个库中,对象能够用C语言中的结构体表示,而方法能够用C函数 来实现,另外再加上了一些额外的特性。这些结构体和函数被runtime函数封装后,咱们就能够在程序运行时建立,检查,修改类、对象和它们的方法了。消息传递
:当程序执行[object doSomething]时,会向消息接收者(object)发送一条消息(doSomething),runtime会根据消息接收者是否能响应该消息而作出不一样的反应。这将在后面详细介绍。在接下来的一系列文章中,我将介绍一下runtime
的基本工做原理以及在咱们的代码里能够用它来作什么。在本文中,咱们先来了解一下类与对象。bash
###OC对象 OC的对象主要能够分为三种:数据结构
instance对象 它主要是经过类alloc出来的对象,每次调用alloc都会产生新的instance对象。app
NSObjcet *object1 = [[NSObjcet alloc] init];
复制代码
instance对象
在内存中存储的信息包括:ide
class对象 咱们经过class方法或runtime方法获得一个class对象。class对象也就是类对象。==每个类在内存中有且只有一个class对象==。函数
Class objectClass1 = [NSObject class];
// runtime
Class objectClass2 = object_getClass(object1);
复制代码
class对象
在内存中存储的信息主要包括:性能
meta-class对象 咱们经过runtime方法获得一个class对象。==每一个类在内存中有且只有一个meta-class对象。==ui
//runtime中传入类对象此时获得的就是元类对象
Class objectMetaClass = object_getClass([NSObject class]);
// 判断该对象是否为元类对象
class_isMetaClass(objectMetaClass)
复制代码
meta-class对象
在内存中存储的信息主要包括:
咱们来看看下面的图,来分析这三者的关系
从上图中,咱们能够分析出:
###Class
Objective-C类是由Class
类型来表示的,它其实是一个指向objc_class
结构体的指针。在objc/objc.h
它的定义以下:
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
复制代码
在objc/runtime.h
中咱们能够看到结构体objc_class
的定义以下:
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_class OBJC2_UNAVAILABLE;// 父类
const char * _Nonnull name OBJC2_UNAVAILABLE;// 类名
long version OBJC2_UNAVAILABLE;// 类的版本信息,默认为0
long info OBJC2_UNAVAILABLE;// 类信息,供运行期使用的一些位标识
long instance_size OBJC2_UNAVAILABLE;// 该类的实例变量大小
struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE;//该类的成员变量链表
struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE;// 方法定义的链表
struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE;// 方法缓存
struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE;// 协议链表
#endif
} OBJC2_UNAVAILABLE;
复制代码
###1. name 类名
// 获取类的类名
const char * class_getName ( Class cls );
复制代码
###2. isa 在Objective-C中,类自身也是一个对象,咱们称之为类对象,在这个类对象中,也有一个isa指针
,它指向了metaClass(元类)
。
###3. super_class 指向该类的父类,若是该类已是最顶层的根类(如NSObject或NSProxy),则super_class
为nil。
###4. instance_size
// 获取实例大小
size_t class_getInstanceSize ( Class cls );
复制代码
###5. objc_ivar_list 成员变量和属性信息。ivars是一个数组,全部的成员变量、属性的信息是放在链表ivars中的。
######获取成员变量信息
// 获取整个成员变量列表
Ivar * class_copyIvarList ( Class cls, unsigned int *outCount );
//获取一个成员变量的名字
const char * _Nullable ivar_getName(Ivar _Nonnull v)
//获取一个成员变量的
const char * _Nullable ivar_getTypeEncoding(Ivar _Nonnull v)
复制代码
ivar_getTypeEncoding
函数获取的是变量的数据类型,详细的说明能够看苹果官方文档Type Encodingsclass_copyIvarLis
t函数,它返回一个指向成员变量信息的数组。这个数组不包含在父类中声明的变量。outCount指针返回数组的大小。须要注意的是,咱们必须使用free()
来释放这个数组。######获取成员变量属性信息
/// An opaque type that represents an Objective-C declared property.
typedef struct objc_property *objc_property_t;
//获取整个成员变量属性列表
objc_property_t _Nonnull *_Nullable class_copyPropertyList(Class _Nullable cls, unsigned int * _Nullable outCount)
/// Defines a property attribute
typedef struct {
const char * _Nonnull name; /**< The name of the attribute */
const char * _Nonnull value; /**< The value of the attribute (usually empty) */
} objc_property_attribute_t;
objc_property_attribute_t * _Nullable property_copyAttributeList(objc_property_t _Nonnull property,unsigned int * _Nullable outCount)
复制代码
objc_property_attribute_t
实际上是对属性的详细描述,包括属性名称、属性编码类型、原子类型/非原子类型等。如T@"NSString",C,N,V_title
,TQ,N,V_age
。下面详细地说明property_getAttributes
获取到的属性的语义:
属性的详细说明Property Type
###6. methodLists 对象方法列表。
/// An opaque type that represents a method in a class definition.
typedef struct objc_method *Method;
struct objc_method {
SEL method_name; // 方法名称
char *method_typesE; // 参数和返回类型的描述字串
IMP method_imp; // 方法的具体的实现的指针
}
复制代码
获取method
信息:
//方法列表
Method _Nonnull * _Nullable class_copyMethodList(Class _Nullable cls, unsigned int * _Nullable outCount)
//方法名
SEL _Nonnull method_getName(Method _Nonnull m)
//方法实现
IMP _Nonnull method_getImplementation(Method _Nonnull m)
//方法参数和返回类型的信息
const char * _Nullable method_getTypeEncoding(Method _Nonnull m)
//方法参数数量
unsigned int method_getNumberOfArguments(Method _Nonnull m)
//方法参数类型
char * _Nullable method_copyArgumentType(Method _Nonnull m, unsigned int index)
复制代码
method_getTypeEncoding
获取函数的编码,其结果是一串值,如:v16@0:8;@16@0:8;v24@0:8@16。这些字符串是什么意思,经过苹果官方文档咱们能够分析出:
###7. cache 用于缓存最近使用的方法。一个接收者对象接收到一个消息时,它会根据isa指针
去查找可以响应这个消息的对象。在实际使用中,这个对象只有一部分方法是经常使用的,不少方法其实不多用或者根本用不上。这种状况下,若是每次消息来时,咱们都是methodLists
中遍历一遍,性能势必不好。这时,cache
就派上用场了。在咱们每次调用过一个方法后,这个方法就会被缓存到cache
列表中,下次调用的时候runtime就会优先去cache
中查找,若是cache
没有,才去methodLists
中查找方法。这样,对于那些常常用到的方法的调用,但提升了调用的效率。
参考: