ivar memory layout

ivar memory layout

设置ivar 修饰符

@implementation XFADModel {
    
    NSString *_ad_id;
    
    // non exist __copy
    __strong NSString *_ad_id_y;
    
    __weak NSString *_ad_id_x;
    
    __unsafe_unretained NSString *_ad_id_xshd;
}


获取ivar修饰符:

class_getIvarLayout, class_getWeakIvarLayout

引用下这个文章:iOS学习之Objective-C Class Ivar Layout的使用


若储存 strong ivar 的 ivarLayout 的值为 0x012000
储存 weak ivar 的 weakIvarLayout 的值为 0x1200
一个 uint8_t 在 16 进制下是两位,所以编码的值每两位一对儿,以上面的 ivarLayout 为
例:
前两位 01 表示有 0 个非 strong 对象和 1 个 strong 对象 之后两位 20 表示有 2 个非 strong 对象和 0 个 strong 对象 最后两位 00 为结束符,就像 cstring 的 \0 一样 同理,上面的 weakIvarLayout:
前两位 12 表示有 1 个非 weak 对象和接下来连续 2 个 weak 对象 00 结束符
这样,用两个 layout 编码值就可以排查出一个 ivar 是属于 strong 还是 weak 的,若都没 有找到,就说明这个对象是 unsafe_unretained.


那么 通过动态创建的ivar 默认的属性是啥呢?
无论是 ivarLayoutweakIvarLayout 其结果反馈指针的值都是0x00,那么默认属性是__unsafe_unretained吗?

看看以下代码:


- (void)setHumanNameValue:(id)aHumanObject {
 
    NSMutableString *fitch = [[NSMutableString alloc]initWithString:@"fitch"];
    [aHumanObject setValue:fitch forKey:@kHuMan_name];
    
    
    [fitch appendFormat:@" Li"];
    
}

以上函数返回后,如果是__unsafe_unretained 属性, 那么在函数返回后, fitch指针会被释放,此时访问再访问kHuMan_name属性,会crash掉,而事实并没有,这说明动态创建ivar,默认属性为 __strong, 那么对于数值类的是怎么处理的呢?


class_addIvar(MyClass, kHuMan_age , sizeof(int), log2(sizeof(int)), @encode(int));


考虑使用一下代码:

- (void)setHumanAge:(id)aHumanObject {
    NSNumber *aNumber = @13;
    NSString *poc = [NSString stringWithFormat:@"%p", &aNumber];
    NSLog(@"%@", poc);
    
    [aHumanObject setValue:aNumber forKey:@kHuMan_age];
    
}


id human_age = [aHumanObject valueForKey:@kHuMan_age];


##################
// human_age = 13

和上面原理一样,当函数退出时,NSNumber会被释放,这里使用log打印指针自身地址,
当,当函数返回时,再查看一下该地址的值,发现值被刷新了,足以说明不是strong,而是assign 其实也可以理解,一个数值类型的怎么strong呢?(不经过malloc出来的数值类型直接存在栈里面,栈退出了,你还指向那个位置有什么用呢?)如果能strong那以什么样的方式用来存储额外的strong信息的。

当NSNumber 存储BOOL 类型的时候,那就是对象了,现在换个Bool 型的,看看是怎么存储的


class_addIvar(MyClass, kHuman_isYoung , sizeof(BOOL), log2(sizeof(BOOL)), @encode(BOOL));


- (void)setHumanIsYoung:(id)aHumanObject {
    NSNumber *aNumber = @YES;
    NSString *poc = [NSString stringWithFormat:@"%p", aNumber];
    NSLog(@"setHumanIsYoung addres: %@", poc);

    [aHumanObject setValue:aNumber forKey:@kHuman_isYoung];
}


id human_isYoung = [aHumanObject valueForKey:@kHuman_isYoung];

Bool Number.png

这里可以看到 ,这下NSNumber是一个对象

总结

对于动态创建的ivar,如果是对象的话 则采用strong引用方式, 是数值则是assign, 但是 使用动态创建的话,ivarLayoutweakIvarLayout的返回值不会刷新, 当然你可以手动设置layout,但是还是不要这么做了,很危险啊,在没有彻底弄明白class内存布局的情况下,贸然使用set layout可能导致非预期的结果

你可能感兴趣的:(ivar memory layout)