runtime机制

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 

@interface NSObject (Ex)

@property (nonatomic, copy) NSString *name;

@end
#import "NSObject+Ex.h"
#import 

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
  • 遍历一个类的成员变量(属性)

相关方法和头文件

  • 头文件

  • 方法

  • 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 

@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机制)