美文网首页
runtime机制

runtime机制

作者: 王蓝胖 | 来源:发表于2016-02-24 02:17 被阅读183次

    runtime是什么

    runtime,即运行时机制。
    runtime是一套底层的纯C的API,是一个C语言库。
    平时写的OC代码,最终都会转成runtime的C语言代码,runtime的幕后工作者。

    比如:
    在OC中:

    [[Person alloc] init];
    

    在runtime中:

    objc_msgSend(objc_msgSend("Person","alloc"),"init");
    

    runtime的应用

    • 拦截系统的方法调用
    • 把OC代码转换为运行时代码,探究底层,比如block的内部实现
    • 字典转模型
    • 在程序运行的状态中,动态创建一个类 (比如KVO底层的实现)
    • 在程序运行的状态中,动态地为某个类添加属性/方法,修改属性值/方法(分类增加属性。
      有人说分类不能增加属性,这是不准确的,分类可以增加属性,并且会自动生成声明,但不会自动生成get/set方法,这时就需要借助runtime来实现)
    #import <Foundation/Foundation.h>
    
    @interface NSObject (Ex)
    
    @property (nonatomic, copy) NSString *name;
    
    @end
    
    #import "NSObject+Ex.h"
    #import <objc/runtime.h>
    
    char namekey;
    
    @implementation NSObject (Ex)
    
    //关联对象函数
    // id object被关联的对象
    // const void *key关联键
    // id value 关联值
    // objc_AssociationPolicy policy 关联策略
    - (void)setName:(NSString *)name{
        objc_setAssociatedObject(self, &namekey, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    
    - (NSString *)name{
        return objc_getAssociatedObject(self, &namekey);
    }
    
    @end
    
    • 遍历一个类的成员变量(属性)

    相关方法和头文件

    • 头文件
      <objc/runtime.h>
      <objc/message.h>

    • 方法

    • NSCoding(归档和解档)

    • 字典转模型(利用runtime遍历模型对象的所有属性,根据属性名从字典里取出相应的值,设置到模型的属性上)

    • KVO(利用runtime动态产生一个类)

    • objc_msgsend给对象发送消息

    • class_copymethodList遍历某个类的方法

    • class_copyIvarList遍历某个类的成员变量

    • class_...

    • class_getClassMethod 获取类方法

    • method_exchangeImplementations 方法交换

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        UIImageView *view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
        view.image = [UIImage imageNamed:@"pic_1"];
        [self.view addSubview:view];
        
    }
    
    @end
    
    #import "UIImage+ExTension.h"
    #import <objc/runtime.h>
    
    @implementation UIImage (ExTension)
    //+ (void)load 只在加载时调用一次
    + (void)load{
        NSLog(@"image load");
        
    //get类方法
        Method m1 = class_getClassMethod([UIImage class], @selector(imageNamed:));
        Method m2 = class_getClassMethod([UIImage class], @selector(my_imageNamed:));
        //方法交换
        method_exchangeImplementations(m1, m2);
    }
    
    //自定义方法
    + (UIImage *)my_imageNamed:(NSString *)name{
        //方法已经被置换,所以此时调用的my_imageNamed:实际上调用的是原方法imageNamed:
        return [UIImage my_imageNamed:@"pic_2"];
    }
    
    @end
    

    程序执行结果显示的就是pic_2,而不是pic_1。方法交换可以用于拦截在运行时拦截一些方法,在执行完自己想要的操作后再跳回该方法。

    • +(void)load 是一个类方法 它在加载进内存时会调用一次
    • +(void)initialize 会在第一次调用类的类方法或实例方法之前被调用一次。

    runtime常识:
    Ivar:成员变量,在runtime中,变量只有一个数据类型,就是Ivar
    Method:成员方法

    相关文章

      网友评论

          本文标题:runtime机制

          本文链接:https://www.haomeiwen.com/subject/npfikttx.html