之前没怎么注意Runtime,最近花了点时间学习了下Runtime。虽然网上的资料很多,但是自己总结一下也是蛮好的。
一,什么是Runtime
runtime即运行时,是一套纯C的API,而Objective-C就是运行时机制的,其中最主要的就是消息机制。
Objective-C是基于C的,它为C添加了面向对象的特性。很泛的说,C+Runtime = Objective-C,可以说Runtime是我们 Objective-C幕后工作者。
我们都知道在编译的时候C语言调用了未实现的函数就会报错;而OC中只要声明了就不会报错,只有当运行的时候才会报错,这是因为OC是运行时动态调用的。
二,Runtime的作用
要想使用runtime,必须要导入头文件,runtime.h
方法发送消息的本质是让对象发送消息,可以通过objc_msgSend让对象发送消息。
runtime 用来干什么呢??用在那些地方呢?怎么用呢?
首先要导入头文件#import <objc/message.h>,其实导入runtime也是可以的,但是message中导入了runtime,所以我们可以直接导入message。
我们所写的OC代码,Xcode最终会将其编译成一份C++文件,生成.opp文件。通过指令 clong -rewrite-objc main.m就会把main.m生成最终代码,它会帮我们做很多的事情,这里没深入进去。
如果说方法发送消息的本质是让对象发送消息的话,我们可以用底层的方法来实现方法发送消息。
但是当我们使用objc_msgSend方法的时候发现,被苹果给注释掉了,这里我们可以在配置里面设置,将其选择为NO,然后我们就可以使用消息机制了,如下图。
执行方法
#假设有一个学生Student类
Student *student = [Student alloc] init];
runtime: objc_msgSend(student, @selector(sayHello));
OC: [self sayHello];
在程序运行过程中, 动态地为某个类添加属性或方法, 修改属性值或方法 遍历一个类的所有成员变量(属性)所有方法
例如:我们需要对一个类的属性进行归档解档的时候属性特别的多,这时候,我们就会写很多对应的代码,但是如果使用了runtime就可以动态设置!
查询类成员变量及类型
/**
* 必备常识:
* Ivar : 成员变量 如果要是动态创建/修改/查看属性,可以使用Ivar
* Method : 成员方法 如果要是动态创建/修改/查看方法,可以使用Method
* 下面的例子教大家一些runtime简单的 查看类中属性和方法以及动态添加属性和方法和修改属性.
*/
/**
* 通过类的名字来获取类里面包含的所有属性
*
* @param className 类名(egs:UIView)
*/
- (void)getIvarsNameListWithClassName:(NSString *)className
{
//通过类的名字获取到类(egs:通过"学生"这个类的名字找到"学生"这个类)
Class ClassName = NSClassFromString(className);
//定义一个变量来存放遍历出来类里面属性的个数
unsigned int outConut = 0;
//查取类里面所有的属性
Ivar * vars = class_copyIvarList([ClassName class], &outConut);
//打印类里面有多少个属性
NSLog(@"%d",outConut);
//遍历类里面所有的属性 和 属性类型
for (int i = 0; i < outConut; i ++) {
//获取类里面属性的名字(将IVar变量转化为字符串)
const char * ivarName = ivar_getName(vars[i]);
//获取类里面属性的类型(获取IVar的类型)
const char * ivarType = ivar_getTypeEncoding(vars[i]);
//打印属性的名字和类型
printf("属性名字:%s 属性类型:%s\n",ivarName,ivarType);
}
查询类方法名及类型
/**
* 通过类的名字,查看类中所有的方法
*
* @param className 类的名字(egs:UIView)
*/
- (void)getMethodNameListWithClassName:(NSString *)className
{
//如果想添加方法直接调用就行了(只需要改一下类)
//添加方法
[self addMethod];
/**
* class_copyMethodList:获取所有方法
* method_getName:读取一个Method类型的变量,输出我们在上层中很熟悉的SEL
*
*/
//通过类的名字,获取到类
Class ClassName = NSClassFromString(className);
//定义一个变量来存放遍历出来类里面属性的个数
unsigned int count = 0;
//查取类里面所有的属性
Method * method = class_copyMethodList(ClassName, &count);
//遍历类里面所有的属性 和 属性类型
for (int i = 0; i < count; i ++) {
//获取类里面方法的名字
SEL methodName = method_getName(method[i]);
//获取类里面方法的类型
const char * methodType = method_copyReturnType(method[i]);
NSLog(@"方法名字:%@,方法类型:%s",NSStringFromSelector(methodName),methodType);
}
}
如有雷同,你就是抄我的!😊😊😊 --大展