一.场景--动态改变变量
unsigned int count = ;
Ivar *ivar = class_copyIvarList([self.person class], &count);
for (int i = ; i<count; i++) {
Ivar var = ivar[i];
const char *varName = ivar_getName(var);
NSString *proname = [NSString stringWithUTF8String:varName]; if ([proname isEqualToString:@"_name"]) { //这里别忘了给属性加下划线
object_setIvar(self.person, var, @"daming");
break;
}
}
NSLog(@"XiaoMing change name is %@",self.person.name);
self.textfield.text = self.self.person.name;
方法说明:
1.Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
用法:返回类的所有属性和变量
参数:class 类型
outCount 类型的数目
返回:Ivar 指针 当做组来用
拓展:class_copyPropertyList 返回对象类的属性(@property申明的属性)
2.const char *ivar_getName(Ivar v)
用法: 返回实例变量的名称。
拓展:ivar_getOffset: 返回实例变量的偏移量。
ivar_getTypeEncoding:返回实例变量的类型字符串。
3. void object_setIvar(id obj, Ivar ivar, id value)
用法:修改类型的变量
参数:obj 所选类
ivar 实例变量
value 更改变量
拓展:id object_getIvar(id obj, Ivar ivar) 获取类实例的变量
二、场景--添加方法
class_addMethod([self.person class], @selector(guess), (IMP)guessAnswer, "v@:");
if ([self.person respondsToSelector:@selector(guess)]) {
//Method method = class_getInstanceMethod([self.xiaoMing class], @selector(guess));
[self.person performSelector:@selector(guess)]; } else{
NSLog(@"Sorry,I don't know");
}
self.textview.text = @"beijing";
1.BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types) //Adds a new method to a class with a given name and implementation.
用法:为类添加一个方法
参数:class 类
SEL 方法选择器 相当于名字
IMP 方法指针
types 描述方法参数类型的字符数组
说明:sel与方法指针名字可以不同 一个是名字 一个是指针地址
三、场景--动态方法交换
self.person = [Person new]; NSLog(@"%@",_person.sayName); NSLog(@"%@",_person.saySex); Method m1 = class_getInstanceMethod([self.person class], @selector(sayName));
Method m2 = class_getInstanceMethod([self.person class], @selector(saySex)); method_exchangeImplementations(m1, m2);
1.Method class_getInstanceMethod(Class cls, SEL name)
用法:获取某类的方法(Method类)
参数:class 类
SEL 方法选择器
2.void method_exchangeImplementations(Method m1, Method m2)
用法:交换方法
参数:Method 方法
四、场景--替换方法
//这里也可以使用 [self.person class],不过要先初始化
Method m1 = class_getInstanceMethod([Person class], @selector(sayName));
Method m2 = class_getInstanceMethod([Tool class], @selector(changeMethod)); method_exchangeImplementations(m1, m2);
用法说过了,嗯!
五:场景--方法上增加额外功能
+ (void)load { static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ Class selfClass = [self class]; SEL oriSEL = @selector(sendAction:to:forEvent:);
Method oriMethod = class_getInstanceMethod(selfClass, oriSEL); SEL cusSEL = @selector(mySendAction:to:forEvent:);
Method cusMethod = class_getInstanceMethod(selfClass, cusSEL); BOOL addSucc = class_addMethod(selfClass, oriSEL, method_getImplementation(cusMethod), method_getTypeEncoding(cusMethod));
if (addSucc) {
class_replaceMethod(selfClass, cusSEL, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod));
}else {
method_exchangeImplementations(oriMethod, cusMethod);
} });
}
- (void)mySendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
[[Tool sharedManager] addCount];
[self mySendAction:action to:target forEvent:event];
}
说明:在程序运行时,Runtime会将所有的Class和Category加载到内存中,这时,会调用类的load方法,通知我们Class或Category已经被加载到内存中。
代码逻辑:交换了方法 ,执行逻辑就改变了 :mySendAction触发->再次调用转到原有sendAction方法
1. IMP method_getImplementation(Method m)
用法:获取IMP
拓展:const char *method_getTypeEncoding(Method m) 获取说明
SEL method_getName(Method m) 获取name(SEL)
2.IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
用法:Replaces the implementation of a method for a given class.
注意:注销 free(ivars);
参考资料来源:https://github.com/Tuccuay/RuntimeSummary