Runtime

Runtime


首先需要导入<objc/runtime.h>
一、Class
获取类的成员变量
Ivar *class_copyIvarList(Class cls,int *outCount);

 unsigned int count;
Ivar *ivars = class_copyIvarList([self class], &count);
// 对变量进行操作
// 使用完成之后要释放ivars
free(ivars);

获取实例方法
Method class_getInstanceMethod(Class cls, SEL name)

        Class originCls = [p class];
Class curCls = [self class];

SEL originSel = @selector(scold:);
SEL curSel = @selector(myScold:);

Method originM = class_getInstanceMethod(originCls,originSel);
Method curM = class_getInstanceMethod(curCls, curSel);

获取类方法
Method class_getClassMethod(Class cls, SEL name)

获取IMP(类的实现)

IMP class_getMethodImplementation(Class cls, SEL name)

获取全部实例方法
Method *class_copyMethodList(Class cls, unsigned int *outCount)

获取类所遵守的所有协议

Protocol * __unsafe_unretained *class_copyProtocolList(Class cls, unsigned int *outCount)

获取类所有属性
objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)

 unsigned int count;
// Ivar *ivars = class_copyIvarList([object class], &count);

objc_property_t *properties = class_copyPropertyList([object class], &count);

动态增加方法
BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

BOOL ok = class_addMethod(originCls, curSel, (IMP)method_getImplementation(curM), method_getTypeEncoding(curM));
   - (void)addMethod{
JKPerson *p = [[JKPerson alloc] init];

// 动态增加方法
class_addMethod([p class], @selector(eat), (IMP)eat, "v@:");
// IMP 是eat函数的指针
// "v@:@",v代表void,无返回值,若返回值为int,则为i;
// @代表 id sel; : 代表 SEL _cmd;
// “v@:@@” 意思是,两个参数的没有返回值。
// 一个Objective-C方法是一个简单的C函数,
// 它至少包含两个参数—self和_cmd。
// 所以,我们的实现函数(IMP参数指向的函数)至少需要两个参数

// 调用新增加的方法
[p performSelector:@selector(eat)];
}

void eat(id self, SEL _cmd){
printf("新来的 ");
}

替换两个方法

IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)

交换两个方法
void method_exchangeImplementations(Method m1, Method m2)

if (ok) {
class_replaceMethod(originCls, originSel, (IMP)method_getImplementation(curM), method_getTypeEncoding(curM));
class_replaceMethod(originCls, curSel, (IMP)method_getImplementation(originM), method_getTypeEncoding(originM));
}else{
method_exchangeImplementations(originM, curM);
}

添加实例变量

class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment, const char *types)

class_addIvar([p class], "sex", sizeof(NSString *), 0, "@");

二、object

获取对象类型

const char *object_getClassName(id obj)

获取实例变量
id object_getIvar(id obj, Ivar ivar)

给变量赋值
void object_setIvar(id obj, Ivar ivar, id value)

object_setIvar(p, class_getInstanceVariable([p class], "sex"), @"m");
NSString *sex = object_getIvar(p, class_getInstanceVariable([p class], "sex"));

三、Ivar
获取变量名
const char *ivar_getName(Ivar v)

获取变量类型等信息

const char *ivar_getTypeEncoding(Ivar v)

四、property(objc_property_t)
获取属性名
const char *property_getName(objc_property_t property)

获取属性类型、值等相关信息

const char *property_getAttributes(objc_property_t property)

 // 属性名称
NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];

NSString *propertyAttribute = [NSString stringWithUTF8String:property_getAttributes(property)]; // T@"NSString",C,N,V_name
// 解析属性类型
NSString *tmpType = [[propertyAttribute componentsSeparatedByString:@","] firstObject];
NSInteger len = tmpType.length;
NSString *propertyType = [tmpType substringWithRange:NSMakeRange(3, len - 4)];

 
原文地址:https://www.cnblogs.com/buakaw/p/5725689.html