不要混淆认为浅拷贝 = copy,深拷贝 = mutableCopy
先说一下深拷贝、浅拷贝、copy、mutableCopy的概念。
深拷贝 和 浅拷贝:
浅拷贝(Shallow Copy) :浅拷贝是指复制对象时,只复制对象的结构和引用,不复制对象中的数据。也就是说,拷贝后的对象和原对象指向同一个内存地址。如果原对象中的元素是可变的,那么修改原对象会影响到拷贝后的对象。
深拷贝(Deep Copy) :深拷贝是指复制对象时,除了复制对象的结构外,还会复制对象中的所有数据。即拷贝后的对象和原对象的数据是完全独立的,会产生新的内存地址。修改原对象不会影响到拷贝后的对象。
copy 和 mutableCopy:
copy:返回一个不可变的拷贝。对于不可变对象(如 NSString),copy 会直接返回自己,不会产生新的内存地址,因为它本身已经是不可变的;对于可变对象(如 NSMutableArray),copy 会返回不可变的拷贝,即不可变的对象,有新的内存地址。
mutableCopy:返回一个可变的拷贝。如果原始对象是不可变的,mutableCopy 会创建一个新的可变对象,和原对象指向不同的内存地址;如果原始对象是可变的,mutableCopy 会创建一个新的可变对象,和原对象指向不同的内存地址。
接下来就是代码验证,附带了打印日志。
NSString *oldModel = @"测试String";
NSString *oldModel2 = [oldModel copy];
NSString *oldModel2_1 = [oldModel mutableCopy];
NSString *oldModel3_1 = oldModel;
NSLog(@"old ---XfPayReportModel NSString %@ ---%p ---- %@ ---%p---- %@ ---%p--- %@ ---%p",oldModel,oldModel,oldModel2,oldModel2,oldModel2_1,oldModel2_1,oldModel3_1,oldModel3_1);
//打印结果:
old ---XfPayReportModel NSString 测试String ---0x105833ef0 ---- 测试String ---0x105833ef0---- 测试String ---0x303f59a40--- 测试String ---0x105833ef0
oldModel = @"adasdaddsasddas";
NSLog(@"old ---XfPayReportModel NSString %@ %@ %@",oldModel,oldModel2,oldModel3_1);
//打印结果:
old ---XfPayReportModel NSString adasdaddsasddas 测试String 测试String
总结:
String类型copy不会有新的内存地址,只是copy了一个新的指针变量,但是由于String不可变,所以无法去改变原本对象的值,当重新赋值是,是将原本对象的指针指向了新的变量内存地址。mutableCopy会开辟新的内存地址,形成行的对象。
此时的copy是浅拷贝,mutableCopy是深拷贝
NSMutableString *oldModel4 = [NSMutableString stringWithString:@"qweqweweqw"];
NSMutableString *oldModel5= oldModel4.mutableCopy;
NSMutableString *oldModel6 = oldModel4.copy;
NSMutableString *oldModel7 = oldModel4;
NSLog(@"old ---XfPayReportModel NSMutableString %@ ---%p ---- %@ ---%p---- %@ ---%p",oldModel4,oldModel4,oldModel5,oldModel5,oldModel6,oldModel6);
//打印结果:
old ---XfPayReportModel NSMutableString qweqweweqw ---0x303f59680 ---- qweqweweqw ---0x303f599b0---- qweqweweqw ---0x303083e00
[oldModel4 appendString:@" World"];
NSLog(@"old ---XfPayReportModel NSMutableString %@ %@ %@",oldModel4,oldModel5,oldModel6,oldModel7);
//打印结果:
old ---XfPayReportModel NSMutableString qweqweweqw World qweqweweqw qweqweweqw qweqweweqw World
总结:
执行copy时,产生新的内存地址。原本可变String变为不可变String。无法继续使用可变String的API,因为继续使用会报错。比如appending函数。
执行mutableCopy时也会产生新的内存地址。仍然为可变String类型。
当对原可变String执行appending函数改变值的时候,执行copy和mubalrCopy产生的新对象都不会受到影响。只有直接赋值的oldModel7会受到影响,变为最新值。
NSDictionary *dict = @{@"aaaa1111":@"bbbbbb11111"};
NSDictionary *dict0 = dict;
NSDictionary *dict1 = [dict copy];
NSDictionary *dict2 = [dict mutableCopy];
NSLog(@"old ---XfPayReportModel NSDictionary---%p ---%p ---%p ---%p---%@ ---%@ ---%@ ---%@", dict, dict0, dict1, dict2, dict, dict0, dict1, dict2);
//打印结果:
old ---XfPayReportModel NSDictionary---0x303083b60 ---0x303083b60 ---0x303083b60 ---0x303091ae0---{
aaaa1111 = bbbbbb11111;
} ---{
aaaa1111 = bbbbbb11111;
} ---{
aaaa1111 = bbbbbb11111;
} ---{
aaaa1111 = bbbbbb11111;
}
总结:如String
NSMutableDictionary *payReportsMap = [NSMutableDictionary dictionary];
[payReportsMap setValue:[NSMutableString stringWithString:@"aaaa"] forKey:[NSMutableString stringWithString:@"bbbb"]];
NSMutableDictionary<NSMutableString *, NSMutableString *> *tempMap = payReportsMap;
NSMutableDictionary<NSMutableString *, NSMutableString *> *tempMap1 = [payReportsMap copy];
NSMutableDictionary<NSMutableString *, NSMutableString *> *tempMap2 = [payReportsMap mutableCopy];
NSLog(@"old ---XfPayReportModel NSMutableDictionary---%p ---%p ---%p ---%p---%@ ---%@ ---%@ ---%@", payReportsMap, tempMap, tempMap1, tempMap2, payReportsMap, tempMap, tempMap1, tempMap2);
//打印结果:
old ---XfPayReportModel NSMutableDictionary---0x303092940 ---0x303092940 ---0x3030d9f00 ---0x3030c78c0---{
bbbb = aaaa;
} ---{
bbbb = aaaa;
} ---{
bbbb = aaaa;
} ---{
bbbb = aaaa;
}
[payReportsMap setValue:[NSMutableString stringWithString:@"aaaa1111"] forKey:[NSMutableString stringWithString:@"ddddd"]];
NSLog(@"old ---XfPayReportModel NSMutableDictionary---%p ---%p ---%p ---%p---%@ ---%@ ---%@ ---%@", payReportsMap, tempMap, tempMap1, tempMap2, payReportsMap, tempMap, tempMap1, tempMap2);
//打印结果:
old ---XfPayReportModel NSMutableDictionary---0x303092940 ---0x303092940 ---0x3030d9f00 ---0x3030c78c0---{
bbbb = aaaa;
ddddd = aaaa1111;
} ---{
bbbb = aaaa;
ddddd = aaaa1111;
} ---{
bbbb = aaaa;
} ---{
bbbb = aaaa;
}
总结:如MutableString
NSMutableArray *array = [NSMutableArray arrayWithArray:@[@"1",@"2"]];
NSMutableArray *array1 = array;
NSMutableArray *array2 = [array copy];
NSMutableArray *array3 = [array mutableCopy];
NSLog(@"old ---XfPayReportModel NSMutableArray ---%p ---%p ---%p ---%p---%@ ---%@ ---%@ ---%@", array, array1, array2, array3, array, array1, array2, array3);
//打印结果:
old ---XfPayReportModel NSMutableArray ---0x303ebde30 ---0x303ebde30 ---0x3030c9c80 ---0x303ebe6a0---(
1,
2
) ---(
1,
2
) ---(
1,
2
) ---(
1,
2
)
[array addObject:@"3"];
[array addObjectsFromArray:@[@"4",@"5"]];
NSLog(@"old ---XfPayReportModel NSMutableArray ---%p ---%p ---%p ---%p---%@ ---%@ ---%@ ---%@", array, array1, array2, array3, array, array1, array2, array3);
//打印结果:
old ---XfPayReportModel NSMutableArray ---0x303ebde30 ---0x303ebde30 ---0x3030c9c80 ---0x303ebe6a0---(
1,
2,
3,
4,
5
) ---(
1,
2,
3,
4,
5
) ---(
1,
2
) ---(
1,
2
)
总结:如MutableString
写在最后:
1.当需要对一个数组,字典操作时,如果是一个共用数组字典,请先copy或者mutableCopy之后再操作,避免多方操作同个字典导致的越界等崩溃。
2.直接的赋值操作=是赋值的变量指针,指向的还是同一块内存地址,所以当原本的对象值发生改变时,会影响到新的对象。所以在复制新的对象后不想再改变的时候,请赋值时使用copy or mutableCopy。