Runtime常见的作用
- 动态变量控制
- 动态交换方法
- 动态添加方法
- 动态为Category扩展加属性
动态变量控制
修改XiaoMing类中的englishName属性值
步骤:
-
动态获取XiaoMing类中的所有属性[当然包括私有]
Ivar *ivar = class_copyIvarList([self.xiaoMing class], &count);
-
遍历属性找到对应name字段
const char *varName = ivar_getName(var);
-
修改对应的字段值成Minggo
object_setIvar(self.xiaoMing, var, @"Minggo");
代码:
-(void)answer{
unsigned int count = 0;
Ivar *ivar = class_copyIvarList([self.xiaoMing 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:@"_englishName"]) {
object_setIvar(self.xiaoMing, var, @"Minggo");
break;
}
}
NSLog(@"XiaoMing first answer is %@",self.xiaoMing.englishName);
self.nameTf.text = self.xiaoMing.englishName;
}
动态交换方法
用XiaoMing类中的secondSay方法替换XiaoMing类中的firstSay方法
步骤:
-
动态找到firstSay和secondSay方法
Method m1 = class_getInstanceMethod([self.xiaoMing class], @selector(firstSay));
Method m2 = class_getInstanceMethod([self.xiaoMing class], @selector(secondSay));
-
交换两个方法
method_exchangeImplementations(m1, m2);
代码:
-(void)answer{
Method m1 = class_getInstanceMethod([self.xiaoMing class], @selector(firstSay));
Method m2 = class_getInstanceMethod([self.xiaoMing class], @selector(secondSay));
method_exchangeImplementations(m1, m2);
NSString *secondName = [self.xiaoMing firstSay];
self.nameTf.text = secondName;
NSLog(@"XiaoMing:My name is %@",secondName);
}
动态添加方法
给XiaoMing类添加guess方法
步骤:
-
动态给XiaoMing类中添加guess方法:
class_addMethod([self.xiaoMing class], @selector(guess), (IMP)guessAnswer, "v@:");
- 这里参数地方说明一下:
- (IMP)guessAnswer 意思是guessAnswer的地址指针;
- "v@:" 意思是,v代表无返回值void,如果是i则代表int;@代表 id sel; : 代表 SEL _cmd;“v@😡@” 意思是,两个参数的没有返回值。
-
调用guess方法响应事件:
- [self.xiaoMing performSelector:@selector(guess)];
-
编写guessAnswer的实现:
void guessAnswer(id self,SEL _cmd){ NSLog(@"He is from GuangTong"); }
- 这个有两个地方留意一下:
- void的前面没有+、-号,因为只是C的代码。
- 必须有两个指定参数(id self,SEL _cmd)
- 这个有两个地方留意一下:
代码:
-(void)answer{
class_addMethod([self.xiaoMing class], @selector(guess), (IMP)guessAnswer, "v@:");
if ([self.xiaoMing respondsToSelector:@selector(guess)]) {
[self.xiaoMing performSelector:@selector(guess)];
} else{
NSLog(@"Sorry,I don't know");
}
self.cityTf.text = @"GuangTong";
}
void guessAnswer(id self,SEL _cmd){
NSLog(@"He is from GuangTong");
}
动态为Category扩展加属性
XCode运行你在Category的.h文件申明@Property,编译通过,但运行时如果没有Runtime处理,进行赋值取值,就马上报错。
为XiaoMing (MutipleName)添加属性
步骤:
-
申明chineseName属性
#import "XiaoMing.h" @interface XiaoMing (MutipleName) @property(nonatomic,copy) NSString *chineseName; @end
-
动态添加属性和实现方法
#import "XiaoMing+MutipleName.h" #import <objc/runtime.h> @implementation XiaoMing (MutipleName) char cName; -(void)setChineseName:(NSString *) chineseName{ objc_setAssociatedObject(self, &cName, chineseName, OBJC_ASSOCIATION_COPY_NONATOMIC); } -(NSString *)chineseName{ return objc_getAssociatedObject(self, &cName); } @end
-
使用chineseName属性
-(void)answer{ NSLog(@"My Chinese name is %@",self.xiaoMing.chineseName); self.chineseNameTf.text = self.xiaoMing.chineseName; }