美文网首页
RunTime回顾

RunTime回顾

作者: 可怜兮兮的木头 | 来源:发表于2018-01-18 09:24 被阅读0次

    前些日工作闲暇时间又看了一遍 南峰子关于RunTime的博客,为了以后查阅方便,还是决定咬牙自己总结一下。

    一、类和对象
    1.Class

    Objective-C类是Class类型的,它实际上是一个指向objc_class结构体的指针。它的定义如下:

    Class aClass = NSClassFromString(@"NSString");
    typedef struct objc_class *Class;
    

    objc_class结构体的定义如下:

    struct objc_class {
        Class _Nonnull isa  OBJC_ISA_AVAILABILITY;                      // isa指针(指向MetaClass)
    #if !__OBJC2__
        Class _Nullable super_class                                  OBJC2_UNAVAILABLE;   // 父类
        const char * _Nonnull name                                   OBJC2_UNAVAILABLE;   // 类名
        long version                                                 OBJC2_UNAVAILABLE;   // 类的版本信息,默认为0
        long info                                                    OBJC2_UNAVAILABLE;   //类信息,供运行期使用的一些位标识
        long instance_size                                           OBJC2_UNAVAILABLE;   //该类的实例变量大小
        struct objc_ivar_list * _Nullable ivars                      OBJC2_UNAVAILABLE;   //该类的成员变量链表
        struct objc_method_list * _Nullable * _Nullable methodLists  OBJC2_UNAVAILABLE;   //方法定义链表
        struct objc_cache * _Nonnull cache                           OBJC2_UNAVAILABLE;   //方法缓存
        struct objc_protocol_list * _Nullable protocols              OBJC2_UNAVAILABLE;   //协议的链表
    #endif
    } OBJC2_UNAVAILABLE;
    

    在Class的定义中,下面几个字段是我们感兴趣的

    • isa : OC中所有的类自身也是一个对象,Class里的isa指针指向它的metaClass(元类)。
    • super_class: 指向该类的父类,如果是根类(NSObject、NSProxy),则super_class为NULL。
    • cache: 用于缓存使用过的方法,防止每次调用方法都去methodLists中查找,提高调用效率。
    2.实例对象

    OC定义对象时,Person *aPerson;Person是Class对象,即objc_class结构体的指针。objc/objc.h类中,定义Class的同时,定义了objc_object的结构体和id,那aPerson是objc_object结构体的指针。

    #if !OBJC_TYPES_DEFINED
    /// An opaque type that represents an Objective-C class.
    typedef struct objc_class *Class;
    
    /// Represents an instance of a class.
    struct objc_object {
        Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
    };
    
    /// A pointer to an instance of a class.
    typedef struct objc_object *id;
    #endif
    

    实例化对象的过程

    Person *aPerson = [[Person alloc]init];
    
    1. Person调用 +alloc方法,因为Person没有实现+alloc方法,所以去super_class(Person继承自NSObject,所以这里super_class是NSObject)查找。
    2. 直到响应+alloc方法,检测Person类,根据所需申请一段内存空间,使用函数class_createInstance来创建一个objc_object,并把isa指针指向Person类。同时+alloc被添加到cache列表里。
    3. 接着执行-init方法,如果Person响应了-init方法,直接将其加入cache表,如果不响应,就去父类中查找,同+alloc
    3.objc_cache

    objc_cache的定义如下:

    struct objc_cache {
        unsigned int mask /* total = mask + 1 */                 OBJC2_UNAVAILABLE;
        unsigned int occupied                                    OBJC2_UNAVAILABLE;
        Method buckets[1]                                        OBJC2_UNAVAILABLE;
    };
    
    4.元类

    OC中类本身也是一个对象,那objc_class的isa指向谁呢?没错,就是元类metaClass,元类的objc_method_list存储了类方法.


    isa指针.jpg
    5.类与对象操作函数

    runtime提供了大量的函数来操作类与对象。
    ①类操作方法 (class_开头)

    //****************************************
                       **内省**
    ****************************************//
    // 判断给定的Class是否是一个元类
    BOOL class_isMetaClass(Class cls);
    // 响应方法判断
    BOOL class_respondsToSelector (Class cls, SEL sel);
    // 遵循协议
    BOOL class_conformsToProtocol (Class cls, Protocol *protocol);
    
    //****************************************
                       **get**
    ****************************************//
    // 获取类的类名
    const char *class_getName(Class cls);
    // 获取类的父类 Ps:cls为Nil或者为根类时,返回Nil
    Class class_getSuperClass(Class cls);
    // 获取实例的大小
    size_t class_getInstanceSize(Class cls);
    // 获取指定名称的成员变量的信息
    Ivar class_getInstanceVariable(Class cls, const char *name);
    // 获取类成员变量 ( 目前OC中未找到类变量)
    Ivar class_getClassVariable (Class cls,const char *name);
    // 获取指定的属性
    objc_property_t class_getProperty (Class cls,const char *name);
    // 获取实例方法
    Method  class_getInstanceMethod (Class cls,SEL name);
    // 获取类方法
    Method class_getClassMethod (Class cls,SEL name);
    // 获取方法的具体实现
    IMP class_getMethodImplementation (Class cls,SEL name);
    IMP class_getMethodImplementation_stret (Class cls, SEL name);
    
    //****************************************
                       **copy**
    ****************************************//
    /***  成员变量列表、属性列表、方法列表、协议列表  ***/
    Ivar * class_copyIvarList (Class cls, unsigned int *outCount);
    objc_property_t * class_copyPropertyList (Class cls, unsigned int *outCount);
    Method * class_copyMethodList (Class cls,unsigned int *outCount);
    Protocol * class_copyProtocolList (Class cls,unsigned int *outCount); 
    // 注:这4个方法获取的对象要free()掉
    //****************************************
                       **add**
    ****************************************//
    // 添加成员变量,参数说明:添加的类、成员变量名、成员变量大小、偏移量、类型
    BOOL class_addIvar (Class cls,const char *name,size_t size,uint8_t alignment,const char *types);
    // eg:class_addIvar(cls, "_ivar1", sizeof(NSString *), log(sizeof(NSString *)), "i");
    // 注:OC不能为已存在的类添加成员变量,动态创建的类才能添加,且必须在objc_allocateClassPair和objc_registerClassPair之间调用。
    // 添加属性
    BOOL class_addProperty (Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount);
    // eg :   objc_property_attribute_t type = {"T", "@\"NSString\""};
              objc_property_attribute_t ownership = { "C", "" };
              objc_property_attribute_t backingivar = { "V", "_ivar1"};
              objc_property_attribute_t attrs[] = {type, ownership, backingivar};
              class_addProperty(cls, "property2", attrs, 3);
    // 添加方法
    BOOL class_addMethod (Class cls,SEL name,IMP imp,const char *types);
    // eg :   class_addMethod(cls, @selector(submethod1), (IMP)imp_submethod1, "v@:");
    // 添加协议
    BOOL class_addProtocol (Class cls, Protocol *protocol);
    
    //****************************************
                     **replace**
    ****************************************//
    // 替换类的属性
    void class_replaceProperty (Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );
    // 替换方法的实现
    IMP class_replaceMethod (Class cls, SEL name, IMP imp, const char *types);
    

    ②实例对象操作方法(objc_ 、 object_)

    //****************************************
                      **get**
    ****************************************//
    // 获取对象实例变量 (ARC 多用object_getIvar,效率比getInstanceVariable快)
    Ivar object_getInstanceVariable(id obj, const char *name, void **outValue);
    // 获取对象中实例变量的值
    id object_getIvar(id obj, Ivar ivar);
    // 获取对象的类名
    const char * object_getClassName(id obj);
    // 获取对象的类
    Class object_getClass(id obj);
    Class objc_getClass(const char *name);
    // 返回指定类的元类
    Class objc_getMetaClass(const char *name);
    // 获取关联对象, get方法
    id objc_getAssociatedObject(self,&myKey);
    
    //****************************************
                      **copy**
    ****************************************//
    // 创建并返回一个指向所有已注册类定义的指针列表
    Class * objc_copyClassList(unsigned int * _Nullable outCount);
    // 返回所有已加载的OC框架和动态库列表
    const char ** objc_copyImageNames(unsigned int * _Nullable outCount);
    // 返回运行时已知的所有协议的数组
    Protocol * _Nonnull * objc_copyProtocolList(unsigned int *outCount);
    // 返回指定框架包含的所有类名数组
    const char * _Nonnull * objc_copyClassNamesForImage(const char *image, unsigned int *outCount);
    
    //****************************************
                      **set**
    ****************************************//
    // 为指定成员变量赋值
    void object_setIvar(id obj, Ivar ivar, id value);
    // 为某个成员变量绑定类
    Class object_setClass(id obj, Class cls);
    // 给指定对象设置一个关联值
    void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
    
    //****************************************
                 **类、对象创建及销毁**
    ****************************************//
    // 释放指定对象占用的内存
    id object_dispose(id obj);
    // 创建一个新类和元类
    Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes);
    // 销毁一个类及其相关联的类
    void objc_disposeClassPair(Class cls);
    // 注册objc_allocateClassPair创建的类
    void objc_registerClassPair(Class cls);
    // 创建实例类
    id class_createInstance(Class cls, size_t extraBytes);
    // 在指定位置创建实例
    id objc_constructInstance(Class cls, void *bytes);
    // 销毁类实例
    void * objc_destructInstance(id obj);
    

    写到一半,遇到问题需要验证、、、 哈哈哈哈哈哈

    相关文章

      网友评论

          本文标题:RunTime回顾

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