copy就是复制得到一个不可变的对象,mutableCopy就是复制得到一个可变的对象。按照不同情况,以下分别举例说明:
1. 对非容器类对象的拷贝(比如 NSString,NSMutableString)
(1)被拷贝对象本身不可变(如NSString),代码展示请往下看:
从以下代码输出内容可以看出:
1.将A直接赋值给B时=>A和B拥有相同的内存地址,其值当然也相同;但A(或B)被重新赋值后,A(或B)拥有了新的内存地址,值也相应改变,然而这样的改变不会影响另一方B(或A),另一方仍然具有跟之前一样的地址和值。
2.将A copy到B时=>A和B拥有相同的内存地址,且当A被重新赋值后,A拥有了新的内存地址,其值也相应改变,但这样的改变不会影响B,B仍然具有跟之前一样的地址和值。
3.将A mutableCopy到B时=>B的地址和A的不相同,B的值可以被重新设定(是setString,而不是指赋值);且A被重新赋值也不会影响B,同样B的改变也不会影响A。
代码从这里开始++++++++++++++++++++++++++++++++++++++++++++++++++
NSLog(@"##############以不可变字符串为原型##########");
NSString *strFirst = @"abc";
NSLog(@"1.strFirst address : %p; %@",strFirst, strFirst);
NSString *strSecond = strFirst;
NSLog(@"2.strSecond address : %p; %@",strSecond, strSecond);
NSString *strFirstCopy = [strFirst copy];//相当于strFirst所指向的地址引用计数+1(地址一样)
NSLog(@"3.strFirstCopy address : %p; %@",strFirstCopy, strFirstCopy);
NSString *strFirstMutableCopy = [strFirst mutableCopy];
NSLog(@"4.strFirstMutableCopy address : %p; %@",strFirstMutableCopy, strFirstMutableCopy);
strFirst = @"bcd";//赋值相当于重新分配地址
NSLog(@"5.strFirst address : %p; %@",strFirst, strFirst);
NSLog(@"5.strSecond address : %p; %@",strSecond, strSecond);//
NSLog(@"5.strFirstCopy address : %p; %@",strFirstCopy, strFirstCopy);
NSLog(@"5.strFirstMutableCopy address : %p; %@",strFirstMutableCopy, strFirstMutableCopy);
对于以上示例代码的控制台输出如下:
2016-04-28 13:46:33.504 copyTest[4299:93432] ##############以不可变字符串为原型##########
2016-04-28 13:46:33.504 copyTest[4299:93432] 1.strFirst address : 0x10244b0e8; abc
2016-04-28 13:46:33.504 copyTest[4299:93432] 2.strSecond address : 0x10244b0e8; abc
2016-04-28 13:46:33.505 copyTest[4299:93432] 3.strFirstCopy address : 0x10244b0e8; abc
2016-04-28 13:46:33.505 copyTest[4299:93432] 4.strFirstMutableCopy address : 0x7f9882c1d410; abc
2016-04-28 13:46:33.505 copyTest[4299:93432] 5.strFirst address : 0x10244b188; bcd
2016-04-28 13:46:33.505 copyTest[4299:93432] 5.strSecond address : 0x10244b0e8; abc
2016-04-28 13:46:33.505 copyTest[4299:93432] 5.strFirstCopy address : 0x10244b0e8; abc
2016-04-28 13:46:33.505 copyTest[4299:93432] 5.strFirstMutableCopy address : 0x7f9882c1d410; abc
(2)被拷贝对象本身可变(如NSMutableString),代码展示请往下看:
从以下代码输出内容可以看出:
1.将A直接赋值给B时=>A和B拥有相同的内存地址,其值当然也相同;当A(或B)被重新设定(是setString,而不是指赋值),另一方值也会跟着改变;但A(或B)被重新赋值后,A(或B)拥有了新的内存地址,值也相应改变,然而这样的改变不会影响另一方B(或A),另一方仍然具有跟之前一样的地址和值。
2.将A copy到B时=>B跟A的地址不同,且B不能被重新设定值(setString),A的改变不会影响B,B的改变也不影响A。
3.将A mutableCopy到B时=>B的地址和A的不相同,B的值也可以被重新设定(是setString,而不是指赋值);且A被重新赋值也不会影响B,同样B的改变也不会影响A。
代码从这里开始++++++++++++++++++++++++++++++++++++++++++++++++++
NSLog(@"##############以可变字符串为原型###########");
NSMutableString *strVFirst = [NSMutableString stringWithString:@"a"];
NSLog(@"1.strVFirst address : %p; %@",strVFirst, strVFirst);
NSMutableString *strVSecond = strVFirst;
NSLog(@"2.strVSecond address : %p; %@",strVSecond, strVSecond);
NSMutableString *strVFirstCopy = [strVFirst copy];
NSLog(@"3.strVFirstCopy address : %p; %@",strVFirstCopy, strVFirstCopy);
NSMutableString *strVFirstMutableCopy = [strVFirst mutableCopy];
NSLog(@"4.strVFirstMutableCopy address : %p; %@",strVFirstMutableCopy, strVFirstMutableCopy);
[strVFirst setString:@"b"];
NSLog(@"5.strVFirst address : %p; %@",strVFirst, strVFirst);
NSLog(@"5.strVSecond address : %p; %@",strVSecond, strVSecond);
NSLog(@"5.strVFirstCopy address : %p; %@",strVFirstCopy, strVFirstCopy);
NSLog(@"5.strVFirstMutableCopy address : %p; %@",strVFirstMutableCopy, strVFirstMutableCopy);
[strVSecond setString:@"c"];
NSLog(@"6.strVFirst address : %p; %@",strVFirst, strVFirst);
NSLog(@"6.strVSecond address : %p; %@",strVSecond, strVSecond);
NSLog(@"6.strVFirstCopy address : %p; %@",strVFirstCopy, strVFirstCopy);
NSLog(@"6.strVFirstMutableCopy address : %p; %@",strVFirstMutableCopy, strVFirstMutableCopy);
[strVFirstMutableCopy setString:@"c"];
NSLog(@"7.strVFirst address : %p; %@",strVFirst, strVFirst);
NSLog(@"7.strVSecond address : %p; %@",strVSecond, strVSecond);
NSLog(@"7.strVFirstCopy address : %p; %@",strVFirstCopy, strVFirstCopy);
NSLog(@"7.strVFirstMutableCopy address : %p; %@",strVFirstMutableCopy, strVFirstMutableCopy);
对于以上示例代码的控制台输出如下:
2016-04-28 13:46:33.505 copyTest[4299:93432] ##############以可变字符串为原型###########
2016-04-28 13:46:33.505 copyTest[4299:93432] 1.strVFirst address : 0x7f9882f99080; a
2016-04-28 13:46:33.505 copyTest[4299:93432] 2.strVSecond address : 0x7f9882f99080; a
2016-04-28 13:46:33.505 copyTest[4299:93432] 3.strVFirstCopy address : 0xa000000000000611; a
2016-04-28 13:46:33.505 copyTest[4299:93432] 4.strVFirstMutableCopy address : 0x7f9882f990c0; a
2016-04-28 13:46:33.505 copyTest[4299:93432] 5.strVFirst address : 0x7f9882f99080; b
2016-04-28 13:46:33.505 copyTest[4299:93432] 5.strVSecond address : 0x7f9882f99080; b
2016-04-28 13:46:33.505 copyTest[4299:93432] 5.strVFirstCopy address : 0xa000000000000611; a
2016-04-28 13:46:33.505 copyTest[4299:93432] 5.strVFirstMutableCopy address : 0x7f9882f990c0; a
2016-04-28 13:46:33.506 copyTest[4299:93432] 6.strVFirst address : 0x7f9882f99080; c
2016-04-28 13:46:33.506 copyTest[4299:93432] 6.strVSecond address : 0x7f9882f99080; c
2016-04-28 13:46:33.506 copyTest[4299:93432] 6.strVFirstCopy address : 0xa000000000000611; a
2016-04-28 13:46:33.506 copyTest[4299:93432] 6.strVFirstMutableCopy address : 0x7f9882f990c0; a
2016-04-28 13:46:33.506 copyTest[4299:93432] 7.strVFirst address : 0x7f9882f99080; c
2016-04-28 13:46:33.506 copyTest[4299:93432] 7.strVSecond address : 0x7f9882f99080; c
2016-04-28 13:46:33.506 copyTest[4299:93432] 7.strVFirstCopy address : 0xa000000000000611; a
2016-04-28 13:46:33.506 copyTest[4299:93432] 7.strVFirstMutableCopy address : 0x7f9882f990c0; c
对于非容器类变量的拷贝可以做个总结:对不可变对象使用copy,相当于引用计数加1,不会分配新的内存;对不可变对象使用mutableCopy,会分配新的内存地址,新旧对象的改变不会互相影响;对可变对象使用copy或mutableCopy,都会分配新的内存,新旧对象的改变不相互影响。