Runtime简介:2-动态改变变量值和动态增加方法
Objective-C具有相当多的动态特性,常见的有动态类型(Dynamic typing),动态绑定(Dynamic binding)和动态加载(Dynamic loading),这些动态特性都是在Cocoa程序开发时较为常用的语言特性。另外,Objective-C的动态特性在运行时Runtime中也体现的淋漓尽致,例如可以动态去修改某个变量/属性的值,以及给某个类动态增加新的方法。
动态修改变量的值
我们继续使用上一篇中定义的Person类,在Person类中,添加一个类方法来为Person类对象赋初始值。
+(instancetype) person{
Person *p = [[Person alloc] init];
p.name = @"shixin";
p.age = 35;
p.height = 1.75;
return p;
}
当我们创建一个Person类对象后,我们可以通过运行时Runtime来找到这个对象对应的所有属性/实例变量,然后对属性进行动态修改。例如,下面的代码中,我们对Person类的对象的name属性的值进行了修改。
/*动态修改属性值*/
-(void)changePropertyValue:(Person *)person {
unsigned int count = 0;
Ivar *ivar = class_copyIvarList([Person class], &count);
for (int i = 0; i<count; i++) {
Ivar var = ivar[i];
const char *varName = ivar_getName(var);
NSString *name = [NSString stringWithUTF8String:varName];
if ([name isEqualToString:@"_name"]) {
//动态修改_name实例变量的值
object_setIvar(person, var, @"sx");
break;
}
}
}
我们可以通过如下代码进行测试调用changePropertyValue:方法前后,person.name对象值。
Person *person = [Person person];
NSLog(@"1--%@--%d--%f", person.name,person.age,person.height);
//动态修改属性的值
[self changePropertyValue:person];
NSLog(@"2--%@--%d--%f", person.name,person.age,person.height);
运行结果如下:
动态增加方法
在Runtime中提供了class_addMethod()函数来给某个类添加一个方法,如下所示,调用该函数需要提供4个参数,其主要含义是:
OBJC_EXPORT BOOL class_addMethod(Class cls, SEL name, IMP imp,
const char *types) ;
- Class cls: 需要添加方法的类名称
- SEL name:需要添加方法对应的选择器的名称(一般和方法同名)
- IMP imp: 新增一个函数来定义新增方法的实现
- const char *types: 新增方法的返回值和参数说明
/*动态添加方法*/
-(void) addMethod:(Person *)person {
//给person对象添加一个addMethod方法
class_addMethod([person class], @selector(addMethod), (IMP)addMethod, "v@:");
//如果Person中没有实现addMethod方法,则调用addMethod方法
if ([person respondsToSelector:@selector(addMethod)]) {
[person performSelector:@selector(addMethod)];
}
}
//新增方法对应的函数实现
void addMethod (id self,SEL _cmd){
NSLog(@"added method execute!");
}
当调用addMethod:方法时,运行结果如下。addMethod()中的代码会被执行。