RunTime 机制的学习_陈hong鑫

来源:互联网 发布:linux分页查看文件 编辑:程序博客网 时间:2024/05/05 16:16


以下主要从编码实现来学习Runtime

一、动态变量的控制

1.场景

有一个Student类,有一个name属性。动态将学生小明的名字改为小李

2.步骤

  • 动态获取Student类中的所有属性(包括私有属性)
Ivar *ivar = class_copyIvarList([xiaoMing class], &count);
  • 遍历属性找到对应的name字段
const char *varName = ivar_getName(var)
  • 修改对应的字段值成小李
object_setIvar(xiaoMing,var,@"小李");
3.完整代码
- (void)method{
Student *xiaoMing = [Student new];
xiaoMing.name = @"小明";

  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:@"_name"]) {

            object_setIvar(self.xiaoMing, var, @"小李");

            break;

        }

     }


}

二.动态交换方法

1、场景

Student类中有两个方法method1 和method2 。调用method1打印调用了方法一,调用method2打印调用了方法二,经过Runtime处理

实现调用method2打印调用了方法一,调用method1打印调用了方法二

2、实现步骤

  • 动态找到method1和method2(这里是动态获取实例方法的函数)

Method m1 = class_getInstanceMethod([xiaoMing class], @selector(method1));

Method m2 = class_getInstanceMethod([xiaoMing class], @selector(method2));

  • 交换两个方法

method_exchangeImplementations(m1, m2);

3、完整代码

-(void)exchangeMethod{


    Method m1 = class_getInstanceMethod([xiaoMing class], @selector(method1));

    Method m2 = class_getInstanceMethod([xiaoMing class], @selector(method2));


    method_exchangeImplementations(m1, m2);

[xiaoMing method1];

[xiaoMing method2];


}

三.动态添加方法

1.场景

Student类中没有play这个方法,由于特殊需要被Runtime添加了一个play方法,再调用这个方法。

2.实现步骤

  • 动态给Student类中添加play方法

class_addMethod([xiaoMing class], @selector(play), (IMP)playStudent, "v@:");

参数说明:

(IMP)playStudent 意思是playStudent的地址指针;

“v@:” 意思是,v代表无返回值void,如果是i则代表int;@代表 id sel; : 代表 SEL _cmd;

“v@:@@” 意思是,两个参数的没有返回值。

  • 用play方法响应事件

[xiaoMing performSelector:@selector(play)];

  • 编写playStudent的实现:
  • void playStudent(id self,SEL _cmd){

     NSLog(@"happy play");   

}

备注:

1.void playStudent(id self,SEL _cmd)是函数

2.必须有两个指定参数(id self,SEL _cmd)


3.完整代码

-(void)takePlay{

    class_addMethod([xiaoMing class], @selector(play), (IMP)playStudent, "v@:");

    if ([xiaoMing respondsToSelector:@selector(play)]) {


        [xiaoMing performSelector:@selector(play)];


    } else{

        NSLog(@"Sorry,I don't know");

    }


}


void playStudent(id self,SEL _cmd){


    NSLog(@"happy play");


}


4.动态为Category扩展属性

1.场景

众所周知在给OC的分类中添加声明@property属性,编译通过,但无法赋值,取值。那么Runtime如何实现可以赋值,取值

以Student类为例,给其分类中动态添加nick属性

2.实现步骤

  • 声明nick属性

#import "Student.h"

@interface Student(TG)

@property(nonatomic,copy) NSString *nick;

@end

  • 动态添加属性和实现方法

@implementation Student (TG)


char cNick;

-(void)setNick:(NSString *) nick{

      objc_setAssociatedObject(self, &cNick, nick, OBJC_ASSOCIATION_COPY_NONATOMIC);

}


-(NSString *)chineseName{

    return objc_getAssociatedObject(self, &cNick);

}

@end

  • 给nick属性赋值,取值

- (void)show{

xiaoMing.nick = @"豆豆";

   NSLog(@"nick name is %@",xiaoMing.nick);

}

重要应用有MjExtesion,AFNetworking框架的应用等

------------------------  陈洪鑫------------------------



0 0
原创粉丝点击