概念:
浅拷贝:不拷贝对象本身,仅仅是拷贝指向对象的指针。
深拷贝:是直接拷贝整个对象内存到另一块内存中。
结论:
mutableCopy(假设是1),copy(假设是0),
浅拷贝(假设是0),深拷贝(假设是1)(集合中叫单层深拷贝),
不可变对象(假设是0),可变对象(假设是1)
它们之间的拷贝就相当于或运算
。
(或运算) | 不可变对象(0) | 可变对象(1) |
---|---|---|
copy(0) | 浅拷贝(0) | 深拷贝(1) |
mutableCopy(1) | 深拷贝(1) | 深拷贝(1) |
以下是测试demo,可以不看
非集合类的copy与mutableCopy
NSString非集合类
1、 可变字符串的copy与mutableCopy
代码示例:
NSMutableString *mutableString = [[NSMutableString alloc] initWithFormat:@"mutableString"];
NSLog(@"mutableString内存地址:%p------指针地址:%p", mutableString, &mutableString);
//copy
NSString *copyMutableString = [mutableString copy];
NSLog(@"copyMutableString内存地址:%p------指针地址:%p", copyMutableString, ©MutableString);
//mutableCopy
NSMutableString *mutableCopyMutableString = [mutableString mutableCopy];
NSLog(@"mutableCopyMutableString内存地址:%p------指针地址:%p", mutableCopyMutableString, &mutableCopyMutableString);
控制台打印结果:
mutableString内存地址:0x6040002563b0------指针地址:0x7fff50fee798
copyMutableString内存地址:0x60400002e8e0------指针地址:0x7fff50fee790
mutableCopyMutableString内存地址:0x600000241890------指针地址:0x7fff50fee788
总结:从控制台打印结果可以看出,可变字符串无论是copy还是mutableCopy出来的对象内存地址、指针地址都发生改变,所以都是深拷贝。
2、不可变字符的copy与mutableCopy
代码示例:
NSString *string = [[NSString alloc] initWithFormat:@"mutableString"];
NSLog(@"string内存地址:%p------指针地址:%p", string, &string);
//copy
NSString *copyString = [string copy];
NSLog(@"copyString内存地址:%p------指针地址:%p", copyString, ©String);
//mutableCopy
NSMutableString *mutableCopyString = [string mutableCopy];
NSLog(@"mutableCopyString内存地址:%p------指针地址:%p", mutableCopyString, &mutableCopyString);
控制台打印结果:
string内存地址:0x600000222160------指针地址:0x7fff5db12798
copyString内存地址:0x600000222160------指针地址:0x7fff5db12790
mutableCopyString内存地址:0x60400044e100------指针地址:0x7fff5db12788
总结:不可变字符copy出来的对象内存地址不变,指针地址改变。而mutableCopy出来的对象内存地址、指针地址都不同。所以不可变字符copy是浅拷贝,mutableCopy是深拷贝。
综上所述:
1、无论是可变字符还是不可变字符mutableCopy出来的对象都是深拷贝。
2、不可变字符copy出来的对象是浅拷贝。
3、不可变字符mutableCopy出来的对象是深拷贝。
集合类的copy与mutableCopy
NSArray、NSDictionary、NSSet等集合类
一、 NSArray类:
1. 不可变NSArray示例代码:
NSArray *array = @[@"1", @"2"];
NSLog(@"array内存地址:%p------指针地址:%p", array, &array);
for (NSString *obj in array) {
NSLog(@"\t obj内存地址:%p", obj);
}
NSArray *copyArray = [array copy];
NSLog(@"copyArray内存地址:%p------指针地址:%p", copyArray, ©Array);
for (NSString *copyArrayObj in copyArray) {
NSLog(@"\t copyArrayObj内存地址:%p", copyArrayObj);
}
NSMutableArray *mutableCopyArray = [array mutableCopy];
NSLog(@"mutableCopyArray内存地址:%p", mutableCopyArray);
for (NSString *mutableCopyArrayObj in copyArray) {
NSLog(@"\t mutableCopyArrayObj内存地址:%p", mutableCopyArrayObj);
}
控制台打印结果:
array内存地址:0x60400003f500------指针地址:0x7fff53164600
obj内存地址:0x10ca9c258
obj内存地址:0x10ca9c278
copyArray内存地址:0x60400003f500------指针地址:0x7fff531645b0
copyArrayObj内存地址:0x10ca9c258
copyArrayObj内存地址:0x10ca9c278
mutableCopyArray内存地址:0x60400044d590------指针地址:0x7fff53164560
mutableCopyArrayObj内存地址:0x10ca9c258
mutableCopyArrayObj内存地址:0x10ca9c278
总结:不可变数组copy出来的对象和数组里面的元素内存地址不变,指针地址改变,所以是浅拷贝;mutableCopy出来的对象内存地址、指针地址都改变,但是数组里面的元素都是相同的内存地址,所以是单层深拷贝。
- 可变NSMutableArray示例代码:
NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithObjects:@"1", @"2", nil];
NSLog(@"mutableArray内存地址:%p------指针地址:%p", mutableArray, &mutableArray);
for (NSString *obj in mutableArray) {
NSLog(@"\t obj内存地址:%p", obj);
}
NSArray *copyMutableArray = [mutableArray copy];
NSLog(@"copyMutableArray内存地址:%p------指针地址:%p", copyMutableArray, ©MutableArray);
for (NSString *copyMutableArrayObj in copyMutableArray) {
NSLog(@"\t copyArrayObj内存地址:%p", copyMutableArrayObj);
}
NSMutableArray *mutableCopyMutableArray = [mutableArray mutableCopy];
NSLog(@"mutableCopyMutableArray内存地址:%p------指针地址:%p", mutableCopyMutableArray, &mutableCopyMutableArray);
for (NSString *mutableCopyMutableArrayObj in mutableCopyMutableArray) {
NSLog(@"\t mutableCopyArrayObj内存地址:%p", mutableCopyMutableArrayObj);
}
控制台打印结果:
mutableArray内存地址:0x60400004e6a0------指针地址:0x7fff5dac6610
obj内存地址:0x10213a258
obj内存地址:0x10213a278
copyMutableArray内存地址:0x604000026120------指针地址:0x7fff5dac65c0
copyArrayObj内存地址:0x10213a258
copyArrayObj内存地址:0x10213a278
mutableCopyMutableArray内存地址:0x60400004f990------指针地址:0x7fff5dac6570
mutableCopyArrayObj内存地址:0x10213a258
mutableCopyArrayObj内存地址:0x10213a278
总结:可变数组无论是copy、mutableCopy出来的对象内存地址、指针地址都发生改变,但元素内存地址不变,所以都是单层深拷贝。
综上所述:
1、无论是可变数组还是不可变数组mutableCopy出来的对象都是单层深拷贝。
2、不可变数组copy出来的对象是浅拷贝。
3、不可变数组mutableCopy出来的对象是单层深拷贝。
二、NSDictionary类:
- 不可变NSDictionary示例代码(与数组结果相同):
NSDictionary *dictionary = @{@"key1" : @"value1"};
NSLog(@"dictionary内存地址:%p------指针地址:%p", dictionary, &dictionary);
[dictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"\t key:%p---value:%p",key , obj);
}];
NSDictionary *copyDictionary = [dictionary copy];
NSLog(@"copyDictionary内存地址:%p------指针地址:%p", copyDictionary, ©Dictionary);
[copyDictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"\t key:%p---value:%p",key , obj);
}];
NSMutableDictionary *mutableCopyDictionary = [dictionary mutableCopy];
NSLog(@"mutableCopyDictionary内存地址:%p------指针地址:%p", mutableCopyDictionary, &mutableCopyDictionary);
[mutableCopyDictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"\t key:%p---value:%p",key , obj);
}];
控制台打印结果:
dictionary内存地址:0x60000003faa0------指针地址:0x7fff5093a780
key:0x10f2c7318---value:0x10f2c7338
copyDictionary内存地址:0x60000003faa0------指针地址:0x7fff5093a778
key:0x10f2c7318---value:0x10f2c7338
mutableCopyDictionary内存地址:0x604000226fe0------指针地址:0x7fff5093a770
key:0x10f2c7318---value:0x10f2c7338
总结:不可变字典copy出来的对象和字典里面的键值对内存地址不变,指针地址改变,所以是浅拷贝;mutableCopy出来的对象内存地址、指针地址都改变,但是字典里面的键值对都是相同的内存地址,所以是单层深拷贝。
- 可变NSMutableDictionary示例代码:
NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1" , @"key1", nil];
NSLog(@"mutableDictionary内存地址:%p------指针地址:%p", mutableDictionary, &mutableDictionary);
[mutableDictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"\t key:%p---value:%p",key , obj);
}];
NSDictionary *copyDictionary = [mutableDictionary copy];
NSLog(@"copyDictionary内存地址:%p------指针地址:%p", copyDictionary, ©Dictionary);
[copyDictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"\t key:%p---value:%p",key , obj);
}];
NSMutableDictionary *mutableCopyDictionary = [mutableDictionary mutableCopy];
NSLog(@"mutableCopyDictionary内存地址:%p------指针地址:%p", mutableCopyDictionary, &mutableCopyDictionary);
[mutableCopyDictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"\t key:%p---value:%p",key , obj);
}];
控制台打印结果:
mutableDictionary内存地址:0x604000032ec0------指针地址:0x7fff5d718798
key:0x1024e9338---value:0x1024e9318
copyDictionary内存地址:0x604000032d60------指针地址:0x7fff5d718790
key:0x1024e9338---value:0x1024e9318
mutableCopyDictionary内存地址:0x604000032d20------指针地址:0x7fff5d718788
key:0x1024e9338---value:0x1024e9318
总结:可变字典无论是copy、mutableCopy出来的对象内存地址、指针地址都发生改变,但是键值对内存地址不变,所以都是单层深拷贝。
综上所述:
1、无论是可变字典还是不可变数组mutableCopy出来的对象都是单层深拷贝。
2、不可变字典copy出来的对象是浅拷贝。
3、不可变字典mutableCopy出来的对象是单层深拷贝。
三、NSSet类
- 不可变NSSet示例代码:(与数组结果相同)
NSSet *set = [NSSet setWithObjects:@"1", nil];
NSLog(@"set内存地址:%p------指针地址:%p", set, &set);
[set enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"\t obj内存地址:%p", obj);
}];
NSSet *copySet = [set copy];
NSLog(@"copySet内存地址:%p------指针地址:%p", copySet, ©Set);
[copySet enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"\t obj内存地址:%p", obj);
}];
NSMutableSet *mutableCopySet = [set mutableCopy];
NSLog(@"mutableCopySet内存地址:%p------指针地址:%p", mutableCopySet, &mutableCopySet);
[mutableCopySet enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"\t obj内存地址:%p", obj);
}];
控制台打印结果:
set内存地址:0x600000244b60------指针地址:0x7fff5b8c2798
obj内存地址:0x10433f318
copySet内存地址:0x600000244b60------指针地址:0x7fff5b8c2790
obj内存地址:0x10433f318
mutableCopySet内存地址:0x60400003dc60------指针地址:0x7fff5b8c2788
obj内存地址:0x10433f318
总结:不可变集合copy出来的对象和集合里面的元素内存地址不变,指针地址改变,所以是浅拷贝;mutableCopy出来的对象内存地址、指针地址都改变,但是集合里面的元素都是相同的内存地址,所以是单层深拷贝。
- 可变NSMutableSet示例:
NSMutableSet *mutableSet = [NSMutableSet setWithObjects:@"1", nil];
NSLog(@"mutableSet内存地址:%p------指针地址:%p", mutableSet, &mutableSet);
[mutableSet enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"\t obj内存地址:%p", obj);
}];
NSSet *copySet = [mutableSet copy];
NSLog(@"copySet内存地址:%p------指针地址:%p", copySet, ©Set);
[copySet enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"\t obj内存地址:%p", obj);
}];
NSMutableSet *mutableCopySet = [mutableSet mutableCopy];
NSLog(@"mutableCopySet内存地址:%p------指针地址:%p", mutableCopySet, &mutableCopySet);
[mutableCopySet enumerateObjectsUsingBlock:^(id _Nonnull obj, BOOL * _Nonnull stop) {
NSLog(@"\t obj内存地址:%p", obj);
}];
控制台打印结果:
mutableSet内存地址:0x604000238140------指针地址:0x7fff52981798
obj内存地址:0x10d280318
copySet内存地址:0x6040002066e0------指针地址:0x7fff52981790
obj内存地址:0x10d280318
mutableCopySet内存地址:0x6040002375a0------指针地址:0x7fff52981788
obj内存地址:0x10d280318
总结:可变集合无论是copy、mutableCopy出来的对象内存地址、指针地址都发生改变,但是元素内存地址不变,所以都是单层深拷贝。
综上所述:
1、无论是可变集合还是不可变集合mutableCopy出来的对象都是单层深拷贝。
2、不可变集合copy出来的对象是浅拷贝。
3、不可变集合mutableCopy出来的对象是单层深拷贝。
鉴于水平有限,如果有错误之处还望批评指正,感谢!