• Objective-C学习之Runtime


    (以下内容均为本人的理解,不敢保证准确性,如有误请指出,谢谢!)

    1.Runtime是什么?

      Runtime是一套组件,Objective-C正因为有了Runtime这套组件,才使得它成为一门完全动态的语言。有了Runtime,我们可以动态决定调用哪个方法(消息传递机制),添加方法,交换方法,给类添加属性,还有字典转模型等。

    2.id类型

      id类型可以指向任何一个对象,编译器在编译的时候无法知道该对象属于哪个类,只能到了程序运行的时候才知道具体属于哪个类

    3.SEL类型

      SEL是selector在Objective-C中的表示类型。selector可以理解为区别方法的ID。

    4.IMP

      IMP是“implementation”的缩写,它是由编译器生成的一个函数指针。当你发起一个消息后,这个函数指针决定了最终执行哪段代码。

    5.Method

      Method代表类中的某个方法的类型。

    6.Ivar

      Ivar代表类中实例变量的类型

    7.objc_property_t

      objc_property_t是属性

    8.Cache

      objc_msgSend每调用一次方法后,就会把该方法缓存到cache列表中,下次的时候,就直接优先从cache列表中寻找,如果cache没有,才从methodLists中查找方法。

    9.Category

      这个就是我们平时所说的类别了,它可以动态的为已存在的类添加新的方法。

    一、消息机制

      ①消息传递机制

      在面向对象编程中,对象调用方法叫发送消息。在编译时,程序的源代码就会从对象发送消息转换成Runtime的objc_msgSend函数调用。

      例如:[receiver oneMethod];转化成objc_msgSend(receiver,oneMethod);

      函数objc_msgSend调用过程大概如下:

        (1)检测这个selector是否要忽略。不忽略则下一步。

        (2)检测target是否为nil对象,nil对象接受任何消息都会忽略。target不为nil对象则下一步

        (3)检测对象里是否有实现方法能响应这个消息,如果没有则向父类查找,如果父类没有则继续向上一级查找,直到根类,如果根类都不能响应,则进入消息转发过程。

      ②消息转发机制

      当对象无法正常处理消息时,则进入这个过程:

        (1)调用resolveInstanceMethod:方法决定是否动态添加方法。如果返回NO则进入下一步。

        (2)调用forwardingTargetForSelector:方法,看当前对象是否有内部对象可以响应消息。有则返回内部对象,否则进入下一步。

        (3)这一步将选择子,参数,接收对象封装成一个NSInvocation对象,然后调用forwardInvocation:方法。这时forwardInvocation:方法的实现有两种:一种是修改接收对象,这种实现与第二步返回内部对象类似;另一种实现则是修改消息,例如追加一个参数或修改selector等。如果forwardInvocation:方法没有实现,则进入下一步。

        (4)到了这一步则调用doesNotRecognizeSelector,如果没有实现这个方法,则会crash,整个消息传递和消息转发过程结束。

    二、Runtime的使用

      要使用Runtime,先包含头文件。如果是模拟器则#import <objc/objc-runtime.h>,如果是真机则

    #import <objc/runtime.h>和#import <objc/message.h>,可如下编写: 

        #if TARGET_IPHONE_SIMULATOR

          #import <objc/objc-runtime.h>

        #else

          #import <objc/runtime.h>

          #import <objc/message.h>

         #endif

      Runtime机制提供了很多有用的方法,部分如下:

        Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes);  //动态创建一个类

        void objc_disposeClassPair(Class cls);  //销毁一个类

        SEL sel_registerName(const char *str);  //注册一个方法

        void objc_registerClassPair(Class cls);  //注册一个类

        void object_setIvar(id obj, Ivar ivar, id value);  //为对象中的实例变量赋值

        BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment, const char *types);   //给类添加变量

        BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);  //给类添加方法

        Ivar class_getInstanceVariable(Class cls, const char *name);  //从类中获取一个实例变量

        objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)  //获取类的所有属性

        const char *property_getName(objc_property_t property)  //通过objc_property_t获取属性名称

        Ivar *class_copyIvarList(Class cls, unsigned int *outCount)  //获取类的所有实例变量(包含属性背后的实例变量)

        const char *ivar_getName(Ivar v)              //通过Ivar获取实例变量的名称

        Method *class_copyMethodList(Class cls, unsigned int *outCount)  //获取类的实例方法(不包括类方法和继承的实例方法)

        SEL method_getName(Method m)    //通过Method获取方法SEL(标识)

        const char *sel_getName(SEL sel)  //通过SEL获取方法具体名称

        unsigned int method_getNumberOfArguments(Method m)  //通过Method获取方法参数个数

        

  • 相关阅读:
    selenium登录csdn,urllib抓取数据
    selenium登录12306,requests抓取数据
    加一
    最后一个单词的长度
    最大子序和
    搜索插入位置
    实现strStr()
    二分查找
    内存对齐
    is_pod类型
  • 原文地址:https://www.cnblogs.com/guitarandcode/p/6542060.html
Copyright © 2020-2023  润新知