前些日工作闲暇时间又看了一遍 南峰子关于RunTime的博客,为了以后查阅方便,还是决定咬牙自己总结一下。
一、类和对象
1.Class
Objective-C类是Class类型的,它实际上是一个指向objc_class结构体的指针。它的定义如下:
Class aClass = NSClassFromString(@"NSString");
typedef struct objc_class *Class;
objc_class结构体的定义如下:
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY; // isa指针(指向MetaClass)
#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;
在Class的定义中,下面几个字段是我们感兴趣的
- isa : OC中所有的类自身也是一个对象,Class里的isa指针指向它的metaClass(元类)。
- super_class: 指向该类的父类,如果是根类(NSObject、NSProxy),则super_class为NULL。
- cache: 用于缓存使用过的方法,防止每次调用方法都去methodLists中查找,提高调用效率。
2.实例对象
OC定义对象时,Person *aPerson;Person是Class对象,即objc_class结构体的指针。objc/objc.h类中,定义Class的同时,定义了objc_object的结构体和id,那aPerson是objc_object结构体的指针。
#if !OBJC_TYPES_DEFINED
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;
/// Represents an instance of a class.
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
/// A pointer to an instance of a class.
typedef struct objc_object *id;
#endif
实例化对象的过程
Person *aPerson = [[Person alloc]init];
- Person调用 +alloc方法,因为Person没有实现+alloc方法,所以去super_class(Person继承自NSObject,所以这里super_class是NSObject)查找。
- 直到响应+alloc方法,检测Person类,根据所需申请一段内存空间,使用函数class_createInstance来创建一个objc_object,并把isa指针指向Person类。同时+alloc被添加到cache列表里。
- 接着执行-init方法,如果Person响应了-init方法,直接将其加入cache表,如果不响应,就去父类中查找,同+alloc
3.objc_cache
objc_cache的定义如下:
struct objc_cache {
unsigned int mask /* total = mask + 1 */ OBJC2_UNAVAILABLE;
unsigned int occupied OBJC2_UNAVAILABLE;
Method buckets[1] OBJC2_UNAVAILABLE;
};
4.元类
OC中类本身也是一个对象,那objc_class的isa指向谁呢?没错,就是元类metaClass,元类的objc_method_list存储了类方法.
5.类与对象操作函数
runtime提供了大量的函数来操作类与对象。
①类操作方法 (class_开头)
//****************************************
**内省**
****************************************//
// 判断给定的Class是否是一个元类
BOOL class_isMetaClass(Class cls);
// 响应方法判断
BOOL class_respondsToSelector (Class cls, SEL sel);
// 遵循协议
BOOL class_conformsToProtocol (Class cls, Protocol *protocol);
//****************************************
**get**
****************************************//
// 获取类的类名
const char *class_getName(Class cls);
// 获取类的父类 Ps:cls为Nil或者为根类时,返回Nil
Class class_getSuperClass(Class cls);
// 获取实例的大小
size_t class_getInstanceSize(Class cls);
// 获取指定名称的成员变量的信息
Ivar class_getInstanceVariable(Class cls, const char *name);
// 获取类成员变量 ( 目前OC中未找到类变量)
Ivar class_getClassVariable (Class cls,const char *name);
// 获取指定的属性
objc_property_t class_getProperty (Class cls,const char *name);
// 获取实例方法
Method class_getInstanceMethod (Class cls,SEL name);
// 获取类方法
Method class_getClassMethod (Class cls,SEL name);
// 获取方法的具体实现
IMP class_getMethodImplementation (Class cls,SEL name);
IMP class_getMethodImplementation_stret (Class cls, SEL name);
//****************************************
**copy**
****************************************//
/*** 成员变量列表、属性列表、方法列表、协议列表 ***/
Ivar * class_copyIvarList (Class cls, unsigned int *outCount);
objc_property_t * class_copyPropertyList (Class cls, unsigned int *outCount);
Method * class_copyMethodList (Class cls,unsigned int *outCount);
Protocol * class_copyProtocolList (Class cls,unsigned int *outCount);
// 注:这4个方法获取的对象要free()掉
//****************************************
**add**
****************************************//
// 添加成员变量,参数说明:添加的类、成员变量名、成员变量大小、偏移量、类型
BOOL class_addIvar (Class cls,const char *name,size_t size,uint8_t alignment,const char *types);
// eg:class_addIvar(cls, "_ivar1", sizeof(NSString *), log(sizeof(NSString *)), "i");
// 注:OC不能为已存在的类添加成员变量,动态创建的类才能添加,且必须在objc_allocateClassPair和objc_registerClassPair之间调用。
// 添加属性
BOOL class_addProperty (Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount);
// eg : objc_property_attribute_t type = {"T", "@\"NSString\""};
objc_property_attribute_t ownership = { "C", "" };
objc_property_attribute_t backingivar = { "V", "_ivar1"};
objc_property_attribute_t attrs[] = {type, ownership, backingivar};
class_addProperty(cls, "property2", attrs, 3);
// 添加方法
BOOL class_addMethod (Class cls,SEL name,IMP imp,const char *types);
// eg : class_addMethod(cls, @selector(submethod1), (IMP)imp_submethod1, "v@:");
// 添加协议
BOOL class_addProtocol (Class cls, Protocol *protocol);
//****************************************
**replace**
****************************************//
// 替换类的属性
void class_replaceProperty (Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );
// 替换方法的实现
IMP class_replaceMethod (Class cls, SEL name, IMP imp, const char *types);
②实例对象操作方法(objc_ 、 object_)
//****************************************
**get**
****************************************//
// 获取对象实例变量 (ARC 多用object_getIvar,效率比getInstanceVariable快)
Ivar object_getInstanceVariable(id obj, const char *name, void **outValue);
// 获取对象中实例变量的值
id object_getIvar(id obj, Ivar ivar);
// 获取对象的类名
const char * object_getClassName(id obj);
// 获取对象的类
Class object_getClass(id obj);
Class objc_getClass(const char *name);
// 返回指定类的元类
Class objc_getMetaClass(const char *name);
// 获取关联对象, get方法
id objc_getAssociatedObject(self,&myKey);
//****************************************
**copy**
****************************************//
// 创建并返回一个指向所有已注册类定义的指针列表
Class * objc_copyClassList(unsigned int * _Nullable outCount);
// 返回所有已加载的OC框架和动态库列表
const char ** objc_copyImageNames(unsigned int * _Nullable outCount);
// 返回运行时已知的所有协议的数组
Protocol * _Nonnull * objc_copyProtocolList(unsigned int *outCount);
// 返回指定框架包含的所有类名数组
const char * _Nonnull * objc_copyClassNamesForImage(const char *image, unsigned int *outCount);
//****************************************
**set**
****************************************//
// 为指定成员变量赋值
void object_setIvar(id obj, Ivar ivar, id value);
// 为某个成员变量绑定类
Class object_setClass(id obj, Class cls);
// 给指定对象设置一个关联值
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
//****************************************
**类、对象创建及销毁**
****************************************//
// 释放指定对象占用的内存
id object_dispose(id obj);
// 创建一个新类和元类
Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes);
// 销毁一个类及其相关联的类
void objc_disposeClassPair(Class cls);
// 注册objc_allocateClassPair创建的类
void objc_registerClassPair(Class cls);
// 创建实例类
id class_createInstance(Class cls, size_t extraBytes);
// 在指定位置创建实例
id objc_constructInstance(Class cls, void *bytes);
// 销毁类实例
void * objc_destructInstance(id obj);