前言
在最开始听到runtime的时候,我是感到恐惧的,多么高大上的东西啊!!!后来,开始在网上查一些资料,可是就是只有那么几篇,看了好久,还不知所云,所以就更加恐惧了!!!!后来经过查看documents 以及一些国外大牛的blogs,终于对runtime有了更深刻的了解!
runtime实现的机制是什么
- runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API。
- 在我们平时编写的OC代码中, 程序运行过程时, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者 比如说,下面一个创建对象的方法中.
举例: OC : [[MJPerson alloc] init]
runtime : objc_msgSend(objc_msgSend("MJPerson" , "alloc"), "init")
runtime 用来干什么呢??用在那些地方呢?怎么用呢?
runtime用来干什么?
runtime是属于OC的底层, 可以进行一些非常底层的操作(用OC是无法现实的, 不好实现)
- 在程序运行过程中, 动态创建一个类(比如KVO的底层实现)
- 在程序运行过程中, 动态地为某个类添加属性\方法, 修改属性值\方法
- 遍历一个类的所有成员变量(属性)\所有方法 例如:我们需要对一个类的属性进行归档解档的时候属性特别的多,这时候,我们就会写很多对应的代码,但是如果使用了runtime就可以动态设置!
runtime用在哪些地方? 怎么用?
应用案例:
#import <objc/runtime.h>
- 给系统分类添加属性
// 运行时给分类添加属性--get方法
- (UIView *)backgroundView {
return objc_getAssociatedObject(self, &backgroundViewKey);
}
// 运行时给分类添加属性--set方法
- (void)setBackgroundView:(UIView *)backgroundView {
objc_setAssociatedObject(self, &backgroundViewKey, backgroundView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- 方法交换(黑魔法)
Method imageNamedMethod = class_getClassMethod(self, @selector(imageNamed:));
// 获取xmg_imageNamed
Method xmg_imageNamedMethod = class_getClassMethod(self, @selector(xmg_imageNamed:));
// 交互方法:runtime
method_exchangeImplementations(imageNamedMethod, xmg_imageNamedMethod);
- 获取对象属性/私有属性
JDGTextField *phoneNumeber = [[JDGTextField alloc] init];
phoneNumeber.placeholder = @"请输入手机号";
[phoneNumeber setValue:[UIColor colorWithRed:246.0/255 green:222.0/255 blue:186.0/255 alpha:1.0] forKeyPath:@"_placeholderLabel.textColor"];
- 字典转模型(KVC)
[self setValuesForKeysWithDictionary:dict];
- KVC 动态获取属性–下拉刷新
self.tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
- 归档解档
1)NSData-归档2个Person对象到同一文件中
归档(编码)
// 新建一块可变数据区
NSMutableData *data = [NSMutableData data];
// 将数据区连接到一个NSKeyedArchiver对象
NSKeyedArchiver *archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:data] autorelease];
// 开始存档对象,存档的数据都会存储到NSMutableData中
[archiver encodeObject:person1 forKey:@"person1"];
[archiver encodeObject:person2 forKey:@"person2"];
// 存档完毕(一定要调用这个方法)
[archiver finishEncoding];
// 将存档的数据写入文件
[data writeToFile:path atomically:YES];
2)NSData-从同一文件中恢复2个Person对象
恢复(解码)
// 从文件中读取数据
NSData *data = [NSData dataWithContentsOfFile:path];
// 根据数据,解析成一个NSKeyedUnarchiver对象
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
Person *person1 = [unarchiver decodeObjectForKey:@"person1"];
Person *person2 = [unarchiver decodeObjectForKey:@"person2"];
// 恢复完毕
[unarchiver finishDecoding];
- NSClassFromString
NSString *vcName = obj[JDGRootVcName];
Class vcClass = NSClassFromString(vcName);
UIViewController *vc = [[vcClass alloc] init];
- block
runtime相关函数
objc_msgSend : 给对象发送消息
class_copyMethodList : 遍历某个类所有的方法
class_copyIvarList : 遍历某个类所有的成员变量
class_..... 这是我们学习runtime必须知道的函数!
runtime原理机制
—未完待续