RunTime

作者: 奋斗的小老鼠 | 来源:发表于2016-07-02 18:04 被阅读26次

    最近看到好多面试要就上提到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,然后我们就可以使用消息机制了,如下图。

    屏幕快照 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

          本文链接:https://www.haomeiwen.com/subject/xgpqjttx.html