本文很大部分借鉴:[http://www.cnblogs.com/tandaxia/p/4475410.html],
自己动手写一下并记录来加深对深拷贝,浅拷贝的理解
一、 属性修饰符strong、copy修饰字符串的区别
先创建一个strTest类定义属性
#import <Foundation/Foundation.h>
@interface stringTest : NSObject
@property (nonatomic, strong) NSString *strStrong;
@property (nonatomic, copy) NSString *strCopy;
@property (nonatomic, strong) NSMutableString *strMutableStrong;
@property (nonatomic, copy) NSMutableString *strMutableCopy;
@end
然后测试代码
stringTest *test = [[stringTest alloc] init];
NSLog(@"-----给字符串属性赋值不可变字符串------");
NSString *string1 = @"str1";
[test setStrStrong:string1];
test.strCopy = string1;
test.strMutableStrong = string1;
test.strMutableCopy = string1;
NSLog(@"------赋值str1的log------");
NSLog(@"string1: %p %@",string1,string1);
NSLog(@"test.strStrong: %p %@", test.strStrong,test.strStrong);
NSLog(@"test.strCopy: %p %@", test.strCopy,test.strCopy);
NSLog(@"test.strMutableStrong: %p %@", test.strMutableStrong,test.strMutableStrong);
NSLog(@"test.strMutableCopy: %p %@\n\n", test.strMutableCopy,test.strMutableCopy);
string1 = @"str2";
NSLog(@"------- 改变原字符串为str2后log -------");
NSLog(@"string1: %p %@",string1,string1);
NSLog(@"test.strStrong: %p %@", test.strStrong,test.strStrong);
NSLog(@"test.strCopy: %p %@", test.strCopy,test.strCopy);
NSLog(@"test.strMutableStrong: %p %@", test.strMutableStrong,test.strMutableStrong);
NSLog(@"test.strMutableCopy: %p %@", test.strMutableCopy,test.strMutableCopy);
NSLog(@"-----------------------------------------------华丽分割线--------------------------------------------");
NSLog(@"-------------给字符串属性赋值可变字符串-----------------");
NSMutableString *MuString = [[NSMutableString alloc] initWithString:@"MuString"];
[test setStrStrong:MuString];
[test setStrCopy:MuString];
test.strMutableStrong = MuString;
test.strMutableCopy = MuString;
NSLog(@"------赋值MuString的log------");
NSLog(@"MuString: %p %@",MuString,MuString);
NSLog(@"test.strStrong: %p %@", test.strStrong,test.strStrong);
NSLog(@"test.strCopy: %p %@", test.strCopy,test.strCopy);
NSLog(@"test.strMutableStrong: %p %@", test.strMutableStrong,test.strMutableStrong);
NSLog(@"test.strMutableCopy: %p %@\n\n", test.strMutableCopy,test.strMutableCopy);
[MuString appendString:@"_test"];
NSLog(@"------- 改变原字符串为MuString_test后log -------");
NSLog(@"MuString: %p %@",MuString,MuString);
NSLog(@"test.strStrong: %p %@", test.strStrong,test.strStrong);
NSLog(@"test.strCopy: %p %@", test.strCopy,test.strCopy);
NSLog(@"test.strMutableStrong: %p %@", test.strMutableStrong,test.strMutableStrong);
NSLog(@"test.strMutableCopy: %p %@", test.strMutableCopy,test.strMutableCopy);
打印结果
2017-06-19 14:03:08.656 bibi[12436:131119] -----给字符串属性赋值不可变字符串------
2017-06-19 14:03:08.656 bibi[12436:131119] ------赋值str1的log------
2017-06-19 14:08:22.727 bibi[12746:135927] string1: 0x1001c40a0 str1
2017-06-19 14:03:08.656 bibi[12436:131119] test.strStrong: 0x1094810a0 str1
2017-06-19 14:03:08.656 bibi[12436:131119] test.strCopy: 0x1094810a0 str1
2017-06-19 14:03:08.657 bibi[12436:131119] test.strMutableStrong: 0x1094810a0 str1
2017-06-19 14:03:08.657 bibi[12436:131119] test.strMutableCopy: 0x1094810a0 str1
2017-06-19 14:03:08.657 bibi[12436:131119] ------- 改变原字符串为str2后log -------
2017-06-19 14:08:22.728 bibi[12746:135927] string1: 0x1001c4180 str2
2017-06-19 14:03:08.657 bibi[12436:131119] test.strStrong: 0x1094810a0 str1
2017-06-19 14:03:08.657 bibi[12436:131119] test.strCopy: 0x1094810a0 str1
2017-06-19 14:03:08.657 bibi[12436:131119] test.strMutableStrong: 0x1094810a0 str1
2017-06-19 14:03:08.658 bibi[12436:131119] test.strMutableCopy: 0x1094810a0 str1
2017-06-19 14:24:18.622 bibi[13655:149113] ------------------------------------华丽分割线-------------
2017-06-19 14:24:18.678 bibi[13655:149113] -------------给字符串属性赋值可变字符串-----------------
2017-06-19 14:24:18.679 bibi[13655:149113] ------赋值MuString的log------
2017-06-19 14:24:18.679 bibi[13655:149113] MuString: 0x60800007e580 MuString
2017-06-19 14:24:18.679 bibi[13655:149113] test.strStrong: 0x60800007e580 MuString
2017-06-19 14:24:18.679 bibi[13655:149113] test.strCopy: 0xa004d05041412da8 MuString
2017-06-19 14:24:18.679 bibi[13655:149113] test.strMutableStrong: 0x60800007e580 MuString
2017-06-19 14:24:18.679 bibi[13655:149113] test.strMutableCopy: 0xa004d05041412da8 MuString
2017-06-19 14:24:18.680 bibi[13655:149113] ------- 改变原字符串为MuString_test后log -------
2017-06-19 14:24:18.680 bibi[13655:149113] MuString: 0x60800007e580 MuString_test
2017-06-19 14:24:18.680 bibi[13655:149113] test.strStrong: 0x60800007e580 MuString_test
2017-06-19 14:24:18.680 bibi[13655:149113] test.strCopy: 0xa004d05041412da8 MuString
2017-06-19 14:24:18.680 bibi[13655:149113] test.strMutableStrong: 0x60800007e580 MuString_test
2017-06-19 14:24:18.680 bibi[13655:149113] test.strMutableCopy: 0xa004d05041412da8 MuString
结论
给字符串属性赋值不可变字符串,strong、copy修饰的可变和不可变字符串属性都是指针拷贝;
给字符串属性赋值可变字符串,strong修饰的可变和不可变字符串属性是指针拷贝,而copy修饰的可变和不可变字符串属性都是内容拷贝。
说明:第一种情况,给字符串属性赋值不可变字符串,虽然strong、copy修饰的属性都是指针拷贝,但
是因为源数据是不可变字符串,导致源数据值改变后,相应的就是另外一个指针地址了,但是这
些属性还是原来的指针,所以值也是原来的值不会改变;
第二种情况,给字符串属性赋值可变字符串,strong修饰的属性是指针拷贝,所以源可变字
符串值改变后,指针没变,则strong修饰的属性指针与源字符串一样,所以值也跟着变化;
而copy修饰的字符串属性是内容拷贝,源字符串的值改变和属性已经没有关系了,因而不会引起属性值改变。
所以,我们如果从效果来看的话,想要源字符串值的改变不引起属性字符串值的改变,只有当源字符串
是可变字符串时,属性才需要用copy修饰,其他情况使用strong,copy修饰效果是一样的,虽然是指
针拷贝,但是源字符串值的改变不会引起属性字符串值的改变。当然我们还是要理解他们的区别才是王
道。所以一般字符串属性都是用copy来修饰,这是最靠谱的用法!
二、字符串调用copy、mutableCopy方法给字符串赋值
先看代码
//不可变字符串
NSString *str = @"str";
NSString *str1 = [str copy]; //指针拷贝
NSString *str2 = [str mutableCopy]; //内容拷贝
NSMutableString *str3 = [str copy]; //指针拷贝
NSMutableString *str4 = [str mutableCopy]; //内容拷贝
NSLog(@"指针1:%p, %p, %p, %p, %p", str, str1, str2, str3, str4);
/*
指针1:0x1041093f0, 0x1041093f0, 0x7f951840b6e0, 0x1041093f0, 0x7f951840dfe0
*/
//可变字符串
NSMutableString *str5 = [NSMutableString stringWithString:@"MuStr"];
str1 = [str5 copy]; //内容拷贝
str2 = [str5 mutableCopy]; //内容拷贝
str3 = [str5 copy]; //内容拷贝
str4 = [str5 mutableCopy]; //内容拷贝
NSLog(@"指针2:%p, %p, %p, %p, %p", str5, str1, str2, str3, str4);
NSLog(@"值2:%@, %@, %@, %@, %@", str5, str1, str2, str3, str4);
/*
指针2:0x7f9518410af0, 0x7f9518435840, 0x7f9518416390, 0x7f9518403a00, 0x7f951840b6e0
值2:Mustr, Mustr, Mustr, Mustr, Mustr
*/
[str5 appendString:@"_test"];
NSLog(@"指针3:%p, %p, %p, %p, %p", str5, str1, str2, str3, str4);
NSLog(@"值3:%@, %@, %@, %@, %@", str5, str1, str2, str3, str4);
/*
指针3:0x7f9518410af0, 0x7f9518435840, 0x7f9518416390, 0x7f9518403a00, 0x7f951840b6e0
值3:Mustr_test, Mustr, Mustr, Mustr, Mustr
*/
结论:1)、不可变字符串使用copy方法赋值给其他可变或不可变字符串,都是指针拷贝;
2)、不可变字符串使用mutableCopy方法赋值给可变或不可变字符串,和可变字符串使用copy方法或者mutableCopy方法赋值给其他可变或不可变字符串,都是内容拷贝
给属性字符串赋值
stringTest *test = [[stringTest alloc] init];
NSString *str = @"str1";
//不可变字符串调用copy方法,全部指针拷贝
test.strStrong = [str copy];
test.strCopy = [str copy];
test.strMutableStrong = [str copy];
test.strMutableCopy = [str copy];
NSLog(@"指针1:%p, %p, %p, %p, %p", str, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
NSLog(@"指针1:%@, %@, %@, %@, %@", str, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
//指针1:0x101be34f0, 0x101be34f0, 0x101be34f0, 0x101be34f0, 0x101be34f0
//指针1:str1, str1, str1, str1, str1
//不可变字符串调用mutableCopy方法,全部内容拷贝
str = @"str2";
test.strStrong = [str mutableCopy];
test.strCopy = [str mutableCopy];
test.strMutableStrong = [str mutableCopy];
test.strMutableCopy = [str mutableCopy];
NSLog(@"指针2:%p, %p, %p, %p, %p", str, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
NSLog(@"指针2:%@, %@, %@, %@, %@", str, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
//指针2:0x101be3510, 0x7ff939498790, 0x7ff9394a2020, 0x7ff9394970c0, 0x7ff939405d40
//指针2:str2, str2, str2, str2, str2
//可变字符串调用copy方法,全部内容拷贝
NSMutableString *str2 = [NSMutableString stringWithString:@"MuStr1"];
test.strStrong = [str2 copy];
test.strCopy = [str2 copy];
test.strMutableStrong = [str2 copy];
test.strMutableCopy = [str2 copy];
NSLog(@"指针3:%p, %p, %p, %p, %p", str2, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
NSLog(@"指针3:%@, %@, %@, %@, %@", str2, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
//指针3:0x7ff93951f540, 0x7ff93954a100, 0x7ff9395288c0, 0x7ff939516ca0, 0x7ff939548db0
//指针3:MuStr1, MuStr1, MuStr1, MuStr1, MuStr1
//可变字符串调用mutableCopy方法,全部内容拷贝
[str2 appendString:@"MuStr2"];
test.strStrong = [str2 mutableCopy];
test.strCopy = [str2 mutableCopy];
test.strMutableStrong = [str2 mutableCopy];
test.strMutableCopy = [str2 mutableCopy];
NSLog(@"指针4:%p, %p, %p, %p, %p", str2, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
NSLog(@"指针4:%@, %@, %@, %@, %@", str2, test.strStrong, test.strCopy, test.strMutableStrong, test.strMutableCopy);
//指针4:0x7ff93951f540, 0x7ff93951f320, 0x7ff93954a100, 0x7ff9395627b0, 0x7ff939516ca0
//指针4:MuStr1MuStr2, MuStr1MuStr2, MuStr1MuStr2, MuStr1MuStr2, MuStr1MuStr2
结论:1)、不可变字符串调用copy给strong, copy修饰的属性赋值,都是指针拷贝;
2)、不可变字符串调用mutableCopy, 和可变字符串调用copy,和可变字符串调用mutableCopy方法给strong、copy修饰的属性赋值,都是内容拷贝
结论
属性修饰符copy不一定代表着深拷贝,碰上数据源为不可变数据则是浅拷贝(指针拷贝),碰上数据源是可变数据则是深拷贝(内容拷贝);
NSObject的方法copy也不一定代表着浅拷贝,碰上数据源为不可变数据则是浅拷贝,碰上数据源是可变数据则是深拷贝;
NSObject的方法mutableCopy不管数据源是不可变还是可变,都是深拷贝
网友评论