最近看到好多面试要就上提到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);
}
}
网友评论