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,其实导入runtime也是可以的,但是message中导入了runtime,所以我们可以直接导入message。
  我们所写的OC代码,Xcode最终会将其编译成一份c++文件。生成.opp文件。通过指令clong-rewrite-objc main.m就会把main.m生成最终代码,他会帮我们做很多的事情,这里没有深入进去。
  如果说方法发送消失的本质是让对象发送消息的话,我们可以用底层的方法来实现方法发送消息。
  但是我们使用objc_msgSend方法的时候发现,被苹果给注释掉了,这里我们可以在配置文件里面设置,将其选择为NO,然后我们就可以使用消息机制了,如下图。

RunTime_第1张图片
屏幕快照 2016-07-02 下午5.40.22.png
#假设有一个学生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);
    }  
}

你可能感兴趣的:(RunTime)