其实也不算深度解析啦,主要是题目要响亮一点大家才有看的欲望嘛!!!
首先关于Copy想必在面试题中大家见过很多,下面我就写一下我对Copy的理解。
1.Copy是什么???
copy和mutableCopy是方法,是NSObject内定义的方法。
2.Copy有什么用???
copy顾名思义就是拷贝或者说克隆,所以copy的目的就是复制一份原来的内容,进一步思考为什么需要拷贝?显然:拷贝的目的就是改变原来的内容不影响副本,改变副本也不影响原来的内容。
3.从NSString,NSMutableString,NSArray,NSMutableArray说明深拷贝和浅拷贝的区别
首先大家来想一下为什么要用到Copy??Copy的目的所在是什么?为什么需要生成一个新的对象呢???
Copy是为了互不干扰,生成两个对象是为了相互改变的时候不影响另外一个对象。
其次大家要牢记一点,使用Copy方法得到的是不可变对象,使用mutableCopy方法得到的必须是可变对象。
一.NSString、NSMutableString非容器对象分析
1.不可变字符串的copy和mutableCopy
NSString *str = @"xiaoming";
NSString *str1 = [str copy];
NSMutableString * str2 = [str mutableCopy];
NSLog(@"----str:%p,%@,%@----str1:%p,%@,%@----str2:%p,%@,%@",str,str,NSStringFromClass([str class]),str1,str1,NSStringFromClass([str1 class]),str2,str2,NSStringFromClass([str2 class]));
打印结果如下:
----str:0x10c8e4068,xiaoming,__NSCFConstantString----str1:0x10c8e4068,xiaoming,__NSCFConstantString----str2:0x608000266ac0,xiaoming,__NSCFString
通过上面的打印结果大家可以看到不可变的字符串经过copy之后没有生成对象,得到的是不可变字符串,经过mutableCopy之后生成了新的对象,得到是可变字符串。
为什么copy没有得到对象呢???因为原来的对象是不可以修改的,新拷贝的对象也是不可修改的,所以不会影响到另外一个对象。已经符合拷贝的目的 了,所以,OC为了对内存进行优化, 就不会生成一个新的对象。
为什么mutableCopy会生成新的对象呢?生成的是一个可变对象,这样两个对象其中一个对象改变而不影响另外一个对象。
2.可变字符串的copy和mutableCopy
NSMutableString *mulStr = [NSMutableString stringWithFormat:@"abc"];
NSString *mulStr1 = [mulStr copy];
NSMutableString * mulStr2 = [mulStr mutableCopy];
NSLog(@"----str:%p,%@,%@----str1:%p,%@,%@----str2:%p,%@,%@",mulStr,mulStr,NSStringFromClass([mulStr class]),mulStr1,mulStr1,NSStringFromClass([mulStr1 class]),mulStr2,mulStr2,NSStringFromClass([mulStr2 class]));
打印结果如下:
----str:0x600000260180,abc,__NSCFString----str1:0xa000000006362613,abc,NSTaggedPointerString----str2:0x6000002601c0,abc,__NSCFString
通过上面的打印结果可以看出来可变字符串经过copy和mutableCopy之后都创建了新的对象。经过copy之后得到的是不可变字符串,经过mutableCopy之后 得到的是可变字符串。
为什么都会生成对象呢???因为可变字符串本来就是可以改变的,为了改变互不干扰,从而生成新的对象,符合拷贝的目的。
二:NSArray、NSMutableArray容器对象分析
首先容器对象和非容器对象一样同样遵从下面的总结:
如果对一不可变对象复制,copy是指针复制(浅拷贝)、mutableCopy就是对象复制(深拷贝)。
如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。
1.NSArray的copy和mutableCopy
NSArray *array = [[NSArray alloc]initWithObjects:[NSMutableString stringWithFormat:@"a"],@"b",@"c", nil];
NSArray *array1 = [array copy];
NSMutableArray *array2 = [array mutableCopy];
// NSArray *array3 = [array mutableCopy];
NSArray *array3 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array]];
NSLog(@"----array:%p,----array1:%p,-----array2:%p,----array3:%p",array,array1,array2,array3);
NSMutableString *str1 = [array objectAtIndex:0];
[str1 appendString:@"hahhaha"];
[array2 insertObject:@"111111" atIndex:0];
NSMutableString *str2 = [array2 objectAtIndex:1];
[str2 appendString:@"111111"];
NSLog(@"----array:%@,----array1:%@,-----array2:%@,----array3:%@",array,array1,array2,array3);
打印结果如下:
----array:0x608000242070,----array1:0x608000242070,-----array2:0x608000242b50,----array3:0x608000242d90
----array:(
ahahhaha111111,
b,
c
),----array1:(
ahahhaha111111,
b,
c
),-----array2:(
111111,
ahahhaha111111,
b,
c
),----array3:(
a,
b,
c
)
通过上面的打印可以看出来NSArray 经过Copy之后没有创建对象,经过mutableCopy之后创建了新的对象,具体原因和NSString一样,但是里面的元素对象还是指针拷贝,要想做到对象拷贝,可以使用归档的方法。
2.NSMutableArray 的copy和MutableCopy
NSMutableArray *mulArray = [[NSMutableArray alloc]initWithObjects:[NSMutableString stringWithFormat:@"abc"],@"def", nil];
NSMutableArray *mulArray1 = [mulArray copy];
NSMutableArray *mulArray2 = [mulArray mutableCopy];
NSLog(@"----array:%p,----arrar1:%p,----array2:%p",mulArray,mulArray1,mulArray2);
NSMutableString *mulstr = [mulArray objectAtIndex:0];
[mulstr appendString:@"abc"];
NSLog(@"----array:%@,-----array1:%@,-----array2:%@",mulArray,mulArray1,mulArray2);
NSLog(@"----array:%@,-----array1:%@,-----array2:%@",NSStringFromClass([mulArray class]) ,NSStringFromClass([mulArray1 class]),NSStringFromClass([mulArray2 class]));
打印结果如下:
----array:0x60000005af40,----arrar1:0x60000002b1a0,----array2:0x60000005ad60
----array:(
abcabc,
def
),-----array1:(
abcabc,
def
),-----array2:(
abcabc,
def
)
通过上面的打印可以看出来NSArray 经过Copy和mutableCopy之后都创建新的对象,具体原因和NSString一样,但是里面的元素对象还是指针拷贝,要想做到对象拷贝,可以使用归档的方法。
但是大家还要牢记一点:NSMutableArray多次copy每次都会新建对象而NSArray多次copy只新建一次对象。
4.总结
正是因为调用copy方法有时候会生成一个新的对象, 有时候不会生成一个新的对象所以:
如果没有生成新的对象, 我们称之为浅拷贝, 本质就是指针拷贝
如果生成了新的对象, 我们称之为深拷贝, 本质就是会创建一个新的对象
最后:最重要的还是记住拷贝的目的,这样理解深浅拷贝都会变得非常简单,改变原来的内容不影响副本,改变副本也不影响原来的内容