Runtime常见的作用

  1. 动态变量控制
  2. 动态交换方法
  3. 动态添加方法
  4. 动态为Category扩展加属性

动态变量控制

修改XiaoMing类中的englishName属性值

步骤:

  1. 动态获取XiaoMing类中的所有属性[当然包括私有]

    • Ivar *ivar = class_copyIvarList([self.xiaoMing class], &count);
  2. 遍历属性找到对应name字段

    • const char *varName = ivar_getName(var);
  3. 修改对应的字段值成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方法

步骤:

  1. 动态找到firstSay和secondSay方法

    • Method m1 = class_getInstanceMethod([self.xiaoMing class], @selector(firstSay));
    • Method m2 = class_getInstanceMethod([self.xiaoMing class], @selector(secondSay));
  2. 交换两个方法

    • 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方法

步骤:

  1. 动态给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@😡@” 意思是,两个参数的没有返回值。
  2. 调用guess方法响应事件:

    • [self.xiaoMing performSelector:@selector(guess)];
  3. 编写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)添加属性

步骤:

  1. 申明chineseName属性

     #import "XiaoMing.h"
     @interface XiaoMing (MutipleName)
     @property(nonatomic,copy) NSString *chineseName;
     @end
    
  2. 动态添加属性和实现方法

     #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
    
  3. 使用chineseName属性

     -(void)answer{
     NSLog(@"My Chinese name is %@",self.xiaoMing.chineseName);
     self.chineseNameTf.text = self.xiaoMing.chineseName;
     }
    
posted @ 2016-04-07 15:14  孙焱焱  阅读(342)  评论(0编辑  收藏  举报