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)];