1.什么是运行时
1>运行时是套纯C语言的API(纯C语言库)
2>编译器最终都会将OC代码转化为运行时代码
3>利用运行时,可以做很多底层的工作,比如
- 动态添加对象的成员变量和成员方法
- 动态交换两个方法的实现(特别是交换系统自带的方法)
- 获得某个类的所有成员方法,所有成员变量
2.如何应用运行时?
a>将某些OC代码转为运行时代码,探究底层,比如block的实现原理
block实现原理:
b> 拦截系统自带的方法调用,比如拦截imageNamed,viewdidLoad alloc方法
c>实现字典和模型的自动转换
d>能实现分类也可以增加属性
//首先定义一个全局变量,用它的地址作为关联对象的key
static char associatedObjectKey;
//设置关联对象
objc_setAssociatedObject(target, &associatedObjectKey, @"添加的字符串属性", OBJC_ASSOCIATION_RETAIN_NONATOMIC); //获取关联对象
NSString *string = objc_getAssociatedObject(target, &associatedObjectKey);
NSLog(@"AssociatedObject = %@", string);
e>获取某个类的所有成员变量
- 实用价值(实现NSCoding属性的自动归档接档)
如果某个类的属性太多,这样存储就太繁琐
3.运行时常用的函数
- 获得某个类的对象方法<objc/runtime.h>
Method class_getInstanceMethod([self class], systemSel);
- 获得某个类的类方法<objc/runtime.h>
Method class_getInstanceMethod([self class], swizzSel);
- 交换两个方法<objc/runtime.h>
method_exchangeImplementations(systemMethod, swizzMethod);
- 将值vaule跟对象object关联起来(将值vaule存储到对象object中)
objc_setAssociatedObject(id object, const void *key, id vaule, objc_AssociationPolicy policy)
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
};
objc_getAssociatedObject的两个参数。
id object获取谁的关联对象。
const void *key根据这个唯一的key获取关联对象。
其实,你还可以把添加和获取关联对象的方法写在你需要用到这个功能的类的类别中,方便使用。
//添加关联对象
- (void)addAssociatedObject:(id)object{
objc_setAssociatedObject(self, @selector(getAssociatedObject), object, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
//获取关联对象
- (id)getAssociatedObject{
return objc_getAssociatedObject(self, _cmd);
- Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
获得某个类的所有成员变量(outCount会返回成员变量的总数) - const char *ivar_getName(Ivar v)
获得成员变量的名字 - const char *ivar_getTypeEncoding(Ivar v)
获得成员变量的类型 - void free(void *)
释放内存(当C语言函数名中包含copy,create,retain,new等词语,那么就需要在最后释放资源) - 给某个对象发送某个消息 <objc/message.h>
objc_msgSend(target, @selector(doSomething))