Collection对象里的内存管理语义

第一部分 collection包含的基础对象内存管理语义

NSMutableDictionary key、value内存管理语义

    NSMutableString *key = [NSMutableString stringWithFormat:@"%@",@"keykey222"];
    NSMutableString *value = [NSMutableString stringWithFormat:@"%@",@"value111"];
    NSLog(@"%p,%p",key,value);
    NSMutableDictionary *muDic = [NSMutableDictionary dictionary];
    [muDic setObject:value forKey:key];
    NSLog(@"%p,%p",[muDic allKeys][0],[muDic allValues][0]);

输出结果中可以看到,muDic中的value地址同初始化的value是同一个地址,可以证明此时值的语义是“retain”,而键的地址发生了较大的变化,可以肯定的是键是发生了copy操作,而且操作系统在此处更是进行了优化,muDic里面键的类型优化为 NSTaggedPointerString类型

image.png

上述是在键为可变类型时的结果,再看键为不可变类型的情况:

    NSString *key = [NSString stringWithFormat:@"%@",@"keykey222"];
    NSString *value = [NSString stringWithFormat:@"%@",@"value111"];
    NSLog(@"%p,%p",key,value);
    NSMutableDictionary *muDic = [NSMutableDictionary dictionary];
    [muDic setObject:value forKey:key];
    NSLog(@"%p,%p",[muDic allKeys][0],[muDic allValues][0]);

输出结果中键、值的地址均未发生改变,此时键、值均是“retain”操作


image.png

值得注意的是如果muDic初始化方法修改为

NSMutableDictionary *muDic = [NSMutableDictionary dictionaryWithObjectsAndKeys:value,key, nil];

实验结果也是一样的,另外NSDictionary的实验结果同上述完全一致。

NSMutableArray里面对象的内存管理语义

    NSMutableArray *muArray = [NSMutableArray array];
    NSMutableString *object = [NSMutableString stringWithFormat:@"%@",@"object_1"];
    NSLog(@"%p",object);
    [muArray addObject:object];
    NSLog(@"%p",[muArray objectAtIndex:0]);

实验结果:

2019-09-24 09:56:03.392890+0800 ARCMemory[91538:9726448] 0x600000656370
2019-09-24 09:56:03.393089+0800 ARCMemory[91538:9726448] 0x600000656370

地址完全一样,说明array对里面的对象是一个“retain”操作,添加的对象类型为不可变NSString,结果是一样的。
另外,NSArray的实验结果同上述一致,apple这样做也合乎情理,无法保证添加到array里面的对象都可以进行copy操作。

当然,如果有特殊需求,可以使用“toll-free bridging”技术重新定义collection对象里的内存管理语义

第二部分 collection 发生copy、mutableCopy时的内存管理语义

NSDictionary 进行copy操作

    NSString *key = [NSString stringWithFormat:@"%@",@"keykey222"];
    NSString *value = [NSString stringWithFormat:@"%@",@"value111"];
    NSLog(@"原始的key、value地址__%p,%p",key,value);
    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:value,key, nil];
    NSLog(@"dic中key、value的地址__%p,%p",[dic allKeys][0],[dic allValues][0]);
    NSLog(@"dic的地址__%p",dic);

    NSDictionary *copyDic = [dic copy];
    NSLog(@"copyDic的地址__%p",copyDic);
    NSLog(@"copyDic中key、value的地址__%p,%p",[dic allKeys][0],[dic allValues][0]);

打印结果:

2019-09-26 20:12:52.311244+0800 ARCMemory[14154:11058565] 原始的key、value地址__0xbd1d66bd8b110c11,0xbc358bfc8267d770
2019-09-26 20:12:52.311429+0800 ARCMemory[14154:11058565] dic中key、value的地址__0xbd1d66bd8b110c11,0xbc358bfc8267d770
2019-09-26 20:12:52.311575+0800 ARCMemory[14154:11058565] dic的地址__0x600001a638c0
2019-09-26 20:12:52.311672+0800 ARCMemory[14154:11058565] copyDic的地址__0x600001a638c0
2019-09-26 20:12:52.311763+0800 ARCMemory[14154:11058565] copyDic中key、value的地址__0xbd1d66bd8b110c11,0xbc358bfc8267d770

打印结果显示所有对应的地址都是一样的,在新的copyDic里,不仅copyDic是一个retain操作,就连copyDic里面的key、value都是retain操作。

NSDictionary mutableCopy

    NSString *key = [NSString stringWithFormat:@"%@",@"keykey222"];
    NSString *value = [NSString stringWithFormat:@"%@",@"value111"];
    NSLog(@"原始的key、value地址__%p,%p",key,value);
    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:value,key, nil];
    NSLog(@"dic中key、value的地址__%p,%p",[dic allKeys][0],[dic allValues][0]);
    NSLog(@"dic的地址__%p",dic);

    NSDictionary *copyDic = [dic mutableCopy];
    NSLog(@"copyDic的地址__%p",copyDic);
    NSLog(@"copyDic中key、value的地址__%p,%p",[dic allKeys][0],[dic allValues][0]);

//打印结果
2019-09-26 20:21:34.293148+0800 ARCMemory[14403:11067674] 原始的key、value地址__0x8112133e36d57ed9,0x803afe7f3fa3a5b8
2019-09-26 20:21:34.293365+0800 ARCMemory[14403:11067674] dic中key、value的地址__0x8112133e36d57ed9,0x803afe7f3fa3a5b8
2019-09-26 20:21:34.293496+0800 ARCMemory[14403:11067674] dic的地址__0x600001011f80
2019-09-26 20:21:34.293750+0800 ARCMemory[14403:11067674] copyDic的地址__0x600000538380
2019-09-26 20:21:34.293933+0800 ARCMemory[14403:11067674] copyDic中key、value的地址__0x8112133e36d57ed9,0x803afe7f3fa3a5b8

打印结果显示,只是生成的copyDic字典是新地址,此时对字典本身进行了copy操作,但是其它key、value地址均未发生改变,也就是说,字典内部的键值对仍旧是retain操作

NSMutableDictionary copy

只是对Dic本身进行了copy操作,字典内部的key、value均是retain操作,地址不变。

NSMutableDictionary mutableCopy

只是对Dic本身进行了copy操作,字典内部的key、value均是retain操作,地址不变。

NSArray/NSMutableArray 进行copy、mutableCopy时的内存管理语义与上述字典完全一致

你可能感兴趣的:(Collection对象里的内存管理语义)