iOS对象的copy与mutableCopy

概念:

浅拷贝:不拷贝对象本身,仅仅是拷贝指向对象的指针。
深拷贝:是直接拷贝整个对象内存到另一块内存中。

结论:

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出来的对象内存地址、指针地址都改变,但是数组里面的元素都是相同的内存地址,所以是单层深拷贝。

  1. 可变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类:

  1. 不可变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出来的对象内存地址、指针地址都改变,但是字典里面的键值对都是相同的内存地址,所以是单层深拷贝。

  1. 可变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类

  1. 不可变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出来的对象内存地址、指针地址都改变,但是集合里面的元素都是相同的内存地址,所以是单层深拷贝。
  1. 可变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出来的对象是单层深拷贝。

鉴于水平有限,如果有错误之处还望批评指正,感谢!

你可能感兴趣的:(iOS对象的copy与mutableCopy)