美文网首页
runtime之变量和属性

runtime之变量和属性

作者: 骨古 | 来源:发表于2017-12-20 17:02 被阅读16次

    转载文章

    1.Ivar

    1.1 Ivar的类型

    typedef objc_ivar * Ivar;

    struct objc_ivar {
        char *ivar_name;          //ivar名称                          
        char *ivar_type;        //ivar类型
        int ivar_offset;        //ivar偏移量
        #ifdef __LP64__
            int space;
        #endif
    }//ObjC2.0 已过时
    

    Ivar是objc_ivar的指针,包含变量名称,变量类型等成员.

    1.2 为类添加Ivar

    运行时规定,只能在objc_allocateClassPairobjc_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);
    

    1.3 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)
    

    1.4 Ivar的使用

    //在运行时创建继承自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));
    

    2.Property

    2.1 objc_property_t 与 objc_property_attribute_t类型

    typedef struct objc_property *objc_property_t;

    //特性
    typedef struct {
    const char *name;           //特性名称
    const char *value;          //特性的值
    } objc_property_attribute_t;
    
    特效编码 具体含义
    R readonly
    C copy
    & retain
    N nonatomic
    G(name) getter=(name)
    S(name) setter = (name)
    D @dynamic
    W weak
    P 用于垃圾回收

    特性相关编码
    属性的特性字符串 以 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 用于垃圾回收

    2.2 为类添加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)
    

    2.4 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);
    

    相关文章

      网友评论

          本文标题:runtime之变量和属性

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