美文网首页
objc对象说明

objc对象说明

作者: 朽木自雕也 | 来源:发表于2018-10-06 12:06 被阅读116次

    objc_object 对象

    /// 表示类的实例对象
    struct objc_object {
        //isa 为指向类的指针
        Class _Nonnull isa;
    };
    

    什么是class,这就是class

    /// An opaque type that represents an Objective-C class.
    typedef struct objc_class *Class;
    struct objc_class {
        //isa 指向该类的元类
        Class _Nonnull isa;
        //父类
        Class _Nullable super_class;
        //实例对象大小
        long instance_size;
        //属性列表
        struct objc_ivar_list * _Nullable ivars;
        //实例方法列表
        struct objc_method_list * _Nullable * _Nullable methodLists;
        //对象缓存
        struct objc_cache * _Nonnull cache;
        //协议列表
        struct objc_protocol_list * _Nullable protocols;
    
    } OBJC2_UNAVAILABLE;
    

    什么是 Ivar

    /// An opaque type that represents an instance variable.
    typedef struct objc_ivar *Ivar;
    
    struct objc_ivar {
        //变量名称
        char * _Nullable ivar_name;
        //变量类型
        char * _Nullable ivar_type          
        //地址偏移量
        int ivar_offset;
        //变量空间大小
        int space;                       
    }
    

    对 ivar 的访问就可以通过 对象地址
    + ivar偏移字节的方法。但是这又引发一个问题,我们增加了父类的ivar,这个时候布局就出错了,我们就不得不重新编译子类来恢复兼容性。使用Non Fragile ivars时,Runtime会进行检测来调整类中新增的ivar的偏移量。 这样我们就可以通过对象地址
    + 基类大小 + ivar偏移字节的方法来计算出ivar相应的地址,并访问到相应的ivar

    ivar 的用法

    运行时规定,只能在objc_allocateClassPair与objc_registerClassPair两个函数之间为类添加变量

    //额外空间     未知,通常设置为 0
      Class clazz = objc_allocateClassPair(父类class,类名,额外空间);
      //以NSString*为例
      //变量size sizeof(NSString)
      //对齐     指针类型的为log2(sizeof(NSString*))
      //类型     @encode(NSString*)
      BOOL flag = class_addIvar(clazz,变量名,变量size,对齐,类型);
      objc_registerClassPair(clazz);
    

    Ivar的

    //获取Ivar的名称
      const char *ivar_getName(Ivar v);
      //获取Ivar的类型编码,
      const char *ivar_getTypeEncoding(Ivar v)
      //通过变量名称获取类中的实例成员变量
      Ivar class_getInstanceVariable(Class cls, const char *name)
      //通过变量名称获取类中的类成员变量
      Ivar class_getClassVariable(Class cls, const char *name)
      //获取指定类的Ivar列表及Ivar个数
      Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
      //获取实例对象中Ivar的值
      id object_getIvar(id obj, Ivar ivar) 
      //设置实例对象中Ivar的值
      void object_setIvar(id obj, Ivar ivar, id value)
    
    

    还能这样用

    //在运行时创建继承自NSObject的People类
      Class People = objc_allocateClassPair([NSObject class], "People", 0);
      //添加_name成员变量
      BOOL flag1 = class_addIvar(People, "_name", sizeof(NSString*), log2(sizeof(NSString*)), @encode(NSString*));
      if (flag1) {
          NSLog(@"NSString*类型  _name变量添加成功");
      }
      //添加_age成员变量
      BOOL flag2 = class_addIvar(People, "_age", sizeof(int), sizeof(int), @encode(int));
      if (flag2) {
          NSLog(@"int类型 _age变量添加成功");
      }
      //完成People类的创建
      objc_registerClassPair(People);
      unsigned int varCount;
      //拷贝People类中的成员变量列表
      Ivar * varList = class_copyIvarList(People, &varCount);
      for (int i = 0; i<varCount; i++) {
          NSLog(@"%s",ivar_getName(varList[i]));
      }
      //释放varList
      free(varList);
      //创建People对象p1
      id p1 = [[People alloc]init];
      //从类中获取成员变量Ivar
      Ivar nameIvar = class_getInstanceVariable(People, "_name");
      Ivar ageIvar = class_getInstanceVariable(People, "_age");
      //为p1的成员变量赋值
      object_setIvar(p1, nameIvar, @"张三");
      object_setIvar(p1, ageIvar, @33);
      //获取p1成员变量的值
      NSLog(@"%@",object_getIvar(p1, nameIvar));
      NSLog(@"%@",object_getIvar(p1, ageIvar));
    
    

    什么是 Property

    /// Defines a property attribute
    typedef struct {
        //属性名
        const char * _Nonnull name;           /**< The name of the attribute */
        //属性值
        const char * _Nonnull value;          /**< The value of the attribute (usually empty) */
    } objc_property_attribute_t;
    

    特性相关编码
    属性的特性字符串 以 T@encode(type) 开头, 以 V实例变量名称 结尾,中间以特性编码填充,通过property_getAttributes即可查看

    特性编码 具体含义

    R readonly

    C copy

    & retain

    N nonatomic

    G(name) getter=(name)

    S(name) setter=(name)

    D @dynamic

    W weak

    P 用于垃圾回收机制

    为类添加Property

      BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
    

    Property的相关操作

    //替换类中的属性
      void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
      //获取类中的属性
      objc_property_t class_getProperty(Class cls, const char *name)
      //拷贝类中的属性列表
      objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
      //获取属性名称
      const char *property_getName(objc_property_t property)
      //获取属性的特性
      const char *property_getAttributes(objc_property_t property) 
      //拷贝属性的特性列表
      objc_property_attribute_t *property_copyAttributeList(objc_property_t property, unsigned int *outCount)
      //拷贝属性的特性的值
      char *property_copyAttributeValue(objc_property_t property, const char *attributeName)
    

    Property其他用法

    Class People = objc_allocateClassPair([NSObject class], "People", 0);
      objc_registerClassPair(People);
      //T@
      objc_property_attribute_t attribute1;
      attribute1.name = "T";
      attribute1.value=@encode(NSString*);
      //Noatomic
      objc_property_attribute_t attribute2 = {"N",""};//value无意义时通常设置为空
      //Copy
      objc_property_attribute_t attribute3 = {"C",""};
      //V_属性名
      objc_property_attribute_t attribute4 = {"V","_name"};
      //特性数组
      objc_property_attribute_t attributes[] ={attribute1,attribute2,attribute3,attribute4};
      //向People类中添加名为name的属性,属性的4个特性包含在attributes中
      class_addProperty(People, "name", attributes, 4);
      //获取类中的属性列表
      unsigned int propertyCount;
      objc_property_t * properties = class_copyPropertyList(People, &propertyCount);
      for (int i = 0; i<propertyCount; i++) {
          NSLog(@"属性的名称为 : %s",property_getName(properties[i]));
          NSLog(@"属性的特性字符串为: %s",property_getAttributes(properties[i]));
      }
      //释放属性列表数组
      free(properties);
    

    关于 Method

    Method 定义

    /// Defines a method
    struct objc_method_description {
        SEL _Nullable name;               /**< The name of the method */
        char * _Nullable types;           /**< The types of the method arguments */
    };
    
    typedef struct objc_method *Method;
     
    struct objc_method {
        SEL method_name;  // 方法名
        char *method_types;
        IMP method_imp;  // 方法实现
    }
    

    IMP, IMP实际上是一个函数指针,指向方法实现的首地址

    相关操作

    id (*IMP)(id, SEL, ...)
    
    // 调用指定方法的实现
    id method_invoke ( id receiver, Method m, ... );
     
    // 调用返回一个数据结构的方法的实现
    void method_invoke_stret ( id receiver, Method m, ... );
     
    // 获取方法名
    SEL method_getName ( Method m );
     
    // 返回方法的实现
    IMP method_getImplementation ( Method m );
     
    // 获取描述方法参数和返回值类型的字符串
    const char * method_getTypeEncoding ( Method m );
     
    // 获取方法的返回值类型的字符串
    char * method_copyReturnType ( Method m );
     
    // 获取方法的指定位置参数的类型字符串
    char * method_copyArgumentType ( Method m, unsigned int index );
     
    // 通过引用返回方法的返回值类型字符串
    void method_getReturnType ( Method m, char *dst, size_t dst_len );
     
    // 返回方法的参数的个数
    unsigned int method_getNumberOfArguments ( Method m );
     
    // 通过引用返回方法指定位置参数的类型字符串
    void method_getArgumentType ( Method m, unsigned int index, char *dst, size_t dst_len );
     
    // 返回指定方法的方法描述结构体
    struct objc_method_description * method_getDescription ( Method m );
     
    // 设置方法的实现
    IMP method_setImplementation ( Method m, IMP imp );
     
    // 交换两个方法的实现
    void method_exchangeImplementations ( Method m1, Method m2 );
    

    未完,待续。。。。。

    Protocol

    objc_ivar_list

    objc_method_list

    objc_symtab

    objc_cache

    相关文章

      网友评论

          本文标题:objc对象说明

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