首先說下兩個基本定義:
淺復(fù)制:只copy指針而不是copy實際的資源,兩個實例指向內(nèi)存中同一資源。
深復(fù)制:不僅復(fù)制指針,還復(fù)制指針?biāo)赶虻馁Y源,會開辟一塊內(nèi)存存放拷貝的資源。
不可變對象的copy和mutableCopy操作:
不可變數(shù)組
NSArray *arr = [NSArray array];
NSMutableArray *arr1 = arr.copy;
NSMutableArray *arr2 = arr.mutableCopy;
NSLog(@"%p--%p--%p",arr,arr1,arr2);//0x60800001a1b0--0x60800001a1b0--0x608000047290
[arr2 insertObject:@"1" atIndex:0];//插入元素成功
[arr1 insertObject:@"1" atIndex:0];//'-[__NSArray0 insertObject:atIndex:]: unrecognized selector sent to instance
不可變字典
NSDictionary *dict1 = [NSDictionary dictionaryWithObjectsAndKeys:@"value1",@"key1",@"value2",@"key2", nil];
NSMutableDictionary *dicM = dict1.copy;
NSMutableDictionary *dicM1 = dict1.mutableCopy;
NSLog(@"%p--%p--%p",dict1,dicM,dicM1);//0x6000002641c0--0x6000002641c0--0x600000045280
[dicM1 removeObjectForKey:@"key1"];
Printing description of dicM1:
{
key2 = value2;
}
[dicM removeObjectForKey:@"key1"];//-[__NSDictionaryI removeObjectForKey:]: unrecognized selector sent to instance
不可變字符串
NSString *str = @"123";
NSMutableString *strM1 = str.copy;
NSMutableString *strM2 = str.mutableCopy;
NSLog(@"%p--%p--%p",str,strM1,strM2);// 0x1047ee068--0x1047ee068--0x608000079800
[strM2 appendString:@"4"];//Printing description of strM2:
1234
[strM1 appendString:@"5"]; //Attempt to mutate immutable object with appendString:
結(jié)論:對不可變對象進(jìn)行copy操作,不會開辟新的內(nèi)存,copy的只是內(nèi)存地址;對不可變對象進(jìn)行mutableCopy操作,會開辟新的內(nèi)存,拷貝出的對象是可變的;
可變對象的copy和mutableCopy操作:
可變數(shù)組
NSMutableArray *arrM = [NSMutableArray arrayWithCapacity:0];
NSMutableArray *arrM1 = arrM.copy;
NSMutableArray *arrM2 = arrM.mutableCopy;
NSLog(@"%p--%p--%p",arrM,arrM1,arrM2);//arrM:0x608000047e60--arrM1:0x60800000f160--arrM2:0x608000047ce0
[arrM insertObject:@"2" atIndex:0];
[arrM2 insertObject:@"3" atIndex:0];
[arrM1 addObject:@"1"];//-[__NSArray0 addObject:]: unrecognized selector sent to instance
可變字典
NSMutableDictionary *dict1 = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1",@"key1",@"value2",@"key2", nil];
NSMutableDictionary *dicM = dict1.copy;
NSMutableDictionary *dicM1 = dict1.mutableCopy;
NSLog(@"%p--%p--%p",dict1,dicM,dicM1);//0x60000005d7f0--0x600000074780--0x60000005b810
[dicM1 removeObjectForKey:@"key1"];
Printing description of dicM1:
{
key2 = value2;
}
[dicM removeObjectForKey:@"key1"];//-[__NSDictionaryI removeObjectForKey:]: unrecognized selector sent to instance
可變字符串
NSMutableString *str = [NSMutableString stringWithCapacity:0];
NSMutableString *strM1 = str.copy;
NSMutableString *strM2 = str.mutableCopy;
NSLog(@"%p--%p--%p",str,strM1,strM2);//0x6080000716c0--0x103d94570--0x608000071680
[strM2 appendString:@"4"];//Printing description of strM2:
4
[strM1 appendString:@"5"];//Attempt to mutate immutable object with appendString:
結(jié)論:對可變對象進(jìn)行copy操作,會開辟新的內(nèi)存,拷貝出的對象是不可變的;對可變對象進(jìn)行mutableCopy操作,會開辟新的內(nèi)存,拷貝出的對象是可變的;
關(guān)于有可變類型的不可變類(如NSDictionary,NSArray,NSString),聲明屬性時內(nèi)存管理關(guān)鍵字為什么要用copy?
用strong聲明結(jié)果如下:

strong.png

arrStrong.png

strStrong.png
用copy聲明結(jié)果如下:

copy.png

arrCopy.png

strCopy.png
屬性為可變類型,用strong定義,當(dāng)屬性賦值時接收的對象為可變對象,而該可變對象的值改變時,屬性的值也跟著改變了。而用copy修飾,賦值時會拷貝出一個新的不可變對象,不受該可變對象影響;
從上面的結(jié)果能看出copy不等于淺復(fù)制,而mutableCopy一定是深復(fù)制。這是因為拷貝后只要副本和原對象之間相互不影響即可,對于OC中這些不可變的對象,因為他們的值是不能修改的,所以副本和原對象之間滿足相互不影響,沒必要新開辟內(nèi)存空間拷貝一份資源。