身为iOS程序员,但是我对Runtime竟然不熟,实在惭愧,网上搜遍资料,自己整理一下笔记备用。
定义
运行时(runtime)是指在程序运行时才确定数据的类型,调用指定的方法。将数据类型的确定由编译时推迟到了程序运行时。
Runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API。在我们平时编写的OC代码中, 程序运行过程时, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者。
比如:[self addNumber]在运行时会被转化成objc_msgSend(self,@selector(addNumber));
OC中一切都被设计成了对象,我们都知道一个类被初始化成一个实例,这个实例是一个对象。实际上一个类本质上也是一个对象,在runtime中用结构体表示。
头文件
<objc/runtime.h>
类
类在Runtime中以结构体来表示,下面是类的定义:
//类在runtime中的表示
struct objc_class {
Class isa;
#if !__OBJC2__
Class super_class; //指向父类
const char *name; //类名
long version;
long info;
long instance_size
struct objc_ivar_list *ivars //成员变量列表
struct objc_method_list **methodLists; //方法列表
struct objc_cache *cache;//缓存
struct objc_protocol_list *protocols //协议列表
#endif
} OBJC2_UNAVAILABLE
添加一个类
Class myClass=objc_allocateClassPair([NSObject class], "myClass", 0);
Class myClass1=objc_allocateClassPair([NSString class], "myClass1", 0);
NSLog(@"%@",myClass.superclass);
NSLog(@"%@",myClass1.superclass);
打印结果如下:
2017-12-19 14:55:08.179 RunTimeTest[56261:10443894] NSObject
2017-12-19 14:55:08.179 RunTimeTest[56261:10443894] NSString
属性
定义
typedef struct objc_property *objc_property_t;
方法声明:
objc_property_t class_getProperty(Class cls,const char* name);
描述:返回给定类的指定名称的属性的描述信息;返回的objc_property_t类型的内容通过property_getName,property_getAttributes,property_copyAttributeValue,property_copyAttributeList方法查看
方法声明:
objc_property_t* class_copyPropertyList(Class cls,unsigned int* outCount);
描述:
cls需要操作的类
outCount输出指针,指明返回objc_property_t类型数组的大小
返回objc_property_t类型的数组,每个objc_property_t描述一个属性的信息,这个数组中不会包括超类的属性;最后使用完以后,你需要自己通过free方法释放掉这个数组
使用class_copyPropertyList并不会获取无@property声明的成员变量
方法声明:
BOOL class_addProperty(Class cls,const char* name,const objc_property_attribute_t* attributes,unsigned int attributeCount);
描述:给类添加一个属性
cls要修改的类
name属性的名称
attributes属性相关特性的数组
attributeCount数组attributes的个数
如果添加成功则返回YES,添加失败(例如添加的属性已经存在)则返回NO;
方法声明:
void class_replaceProperty(Class cls,const char* name,const objc_property_attribute_t* attributes,unsigned int attributeCount);
描述:替换类的一个属性
cls要修改的类
name属性的名称
attributes属性相关特性的数组
attributeCount数组attributes的个数
方法声明:
const char* property_getName(objc_property_t property);
描述:返回属性描述信息中的属性名称的c字符串
方法声明:
const char* property_getAttributes(objc_property_t property);
描述:返回属性描述信息中的属性特性的c字符串
方法声明:
char* property_copyAttributeValue(objc_property_t property,const char* attributeName);
描述:返回属性描述信息中的属性特性名称为attributeName的c字符串,返回的字符串使用完以后需要自己通过free方法释放掉;
方法声明:
objc_property_attribute_t* property_copyAttributeList(objc_property_t property,unsigned int* outCount);
描述:获取属性的特性的数组,数组的个数会返回给输出指针outCount,返回的数组使用完以后需要自己通过free方法释放掉;
给一个类添加一个额外的属性
//首先定义一个全局变量,用它的地址作为关联对象的key
static char associatedObjectKey;
//设置关联对象
objc_setAssociatedObject(target, &associatedObjectKey, @"添加的字符串属性", OBJC_ASSOCIATION_RETAIN_NONATOMIC); //获取关联对象
NSString *string = objc_getAssociatedObject(target, &associatedObjectKey);
NSLog(@"AssociatedObject = %@", string);
objc_setAssociatedObject的四个参数:
id object 给谁设置关联对象。
const void *key 关联对象唯一的key,获取时会用到。
id value 关联对象。
objc_AssociationPolicy关联策略,有以下几种策略:
enum {
OBJC_ASSOCIATION_ASSIGN = 0,
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1,
OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
OBJC_ASSOCIATION_RETAIN = 01401,
OBJC_ASSOCIATION_COPY = 01403
};
如果你熟悉OC,看名字应该知道这几种策略的意思了吧。
objc_getAssociatedObject的两个参数。
id object获取谁的关联对象。
成员变量
定义
typedef struct objc_ivar *Ivar;
方法声明:
class_copyIvarList(__unsafe_unretained Class cls, unsigned int *outCount)
描述:获取所有成员变量,cls为类名称,outCount为输出指针,指明返回Ivar类型的大小
方法声明:
const char *ivar_getName(Ivar v)
描述:获取当前变量名称,V为变量。
方法声明:
const char *ivar_getTypeEncoding(Ivar v)
描述:获取当前变量编码格式,V为变量
方法声明:
Ivar class_getInstanceVariable(Class cls, const char *name)
描述:获取指定名称的成员变量,cls为当前类,name为变量名称
方法声明:
id object_getIvar(id obj, Ivar ivar)
描述:获取一个成员变量的值,obj为承载变量的对象,ivar为变量
方法声明:
void object_setIvar(id obj, Ivar ivar, id value)
描述:设定指定名称的成员变量,obj为承载变量的对象,ivar为变量,value为变量的值
网友评论