深拷貝和淺拷貝的概念
iOS中有深拷貝和淺拷貝的概念十减,那么何為深拷貝何為淺拷貝呢塑顺?
淺拷貝:淺拷貝并不拷貝對象本身须误,只是對指向?qū)ο蟮闹羔樳M行拷貝
深拷貝:直接拷貝對象到內(nèi)存中一塊區(qū)域,然后把新對象的指針指向這塊內(nèi)存
在iOS中并不是所有對象都支持Copy和MutableCopy,遵循NSCopying協(xié)議的類可以發(fā)送Copy協(xié)議旭绒,遵循NSMutableCopying協(xié)議的類可以發(fā)送MutableCopy消息鸟妙。如果一個對象沒有遵循這兩個協(xié)議而發(fā)送Copy或者MutableCopy消息那么會發(fā)生異常。如果要遵循NSCopying協(xié)議挥吵,那么必須實現(xiàn)copyWithZone方法重父。如果要遵循NSMutableCopying協(xié)議那么必須實現(xiàn)mutableCopyWithZone方法。
可變對象和不可變對象分別調(diào)用Copy和MutableCopy方法的區(qū)別
1.系統(tǒng)非容器類對象
(1)調(diào)用copy和mutableCopy方法
NSString *str = @"123";
NSString *strCopy = [str copy];
NSMutableString *mustr = [str copy];
NSMutableString *muCopy = [str mutableCopy];
[mustr appendString:@"4"]; //會直接崩潰
[muCopy appendString:@"5"];
NSLog(@"str = %@ strCopy = %@ mustr = %@ muCopy = %@",str,strCopy,mustr,muCopy);
NSLog(@"str地址%p strCopy地址%p mustr地址%p muCopy地址%p",str ,strCopy,mustr,muCopy);
輸出結果:
NSMutableString *mustr = [NSMutableString stringWithFormat:@"123"];
NSString *strCopy = [mustr copy];
NSMutableString *mutableStr = [mustr copy];
NSMutableString *mutableStrCopy = [mustr mutableCopy];
[mutableStr appendString:@"5"]; //會崩潰
[mutableStrCopy appendString:@"6"];
NSLog(@"mustr = %@ strCopy = %@ mutableStr = %@ mutableStrCopy = %@",mustr,strCopy,mutableStr,mutableStrCopy);
NSLog(@"mustr地址%p strCopy地址%p mutableStr地址%p mutableStrCopy地址%p",mustr,strCopy,mutableStr,mutableStrCopy);
輸出結果:
從上面可以看出對系統(tǒng)非容器類不可變對象調(diào)用Copy方法其實只是把當前對象的指針指向了原對象的地址忽匈,而調(diào)用mutableCopy方法則是新分配了一塊內(nèi)存區(qū)域并把新對象的指針指向了這塊區(qū)域房午。對于可變對象來說調(diào)用Copy和MutableCopy方法都會重新分配一塊內(nèi)存。但是copy和mutableCopy的區(qū)別在于copy在復制對象的時候其實是返回了一個不可變對象丹允,因此當調(diào)用方法改變對象的時候會崩潰(個人猜測這一塊可能和OC的多態(tài)性有關)郭厌。
2.系統(tǒng)容器類對象
(1)調(diào)用copy和mutableCopy方法
NSArray *array = [NSArray arrayWithObjects:@"1",@"2",@"3", nil];
NSArray *arrayCopy = [array copy];
NSMutableArray *muarray = [array copy];
NSMutableArray *copyArray = [array mutableCopy];
NSLog(@"array地址%p arrayCopy地址%p muarray地址%p copyArray地址%p",array,arrayCopy,muarray,copyArray);
輸出結果:
NSMutableArray *muarray = [NSMutableArray arrayWithObjects:@"1",@"2",@"3", nil];
NSArray *array = [muarray copy];
NSArray *mutableCopy = [muarray mutableCopy];
NSMutableArray *muCopy = [muarray copy];
NSMutableArray *arrayCopy = [muarray mutableCopy];
NSLog(@"muarray地址%p array地址%p mutableCopy地址%p muCopy地址%p arrayCpy地址%p",muarray,array,mutableCopy,muCopy,arrayCopy);
輸出結果:
從這上面看容器對象和非容器對象在分別調(diào)用Copy和MutableCopy時沒有什么分別,不可變對象調(diào)用Copy方法只是增加了對原對象的指針的引用雕蔽,調(diào)用MutableCopy方法是重新分配一塊內(nèi)存折柠,然后把新對象指向新內(nèi)存。而對于可變對象不管調(diào)用Copy還是MutableCopy都是新分配一塊內(nèi)存批狐。但是雖然重新分配了一塊內(nèi)存扇售,但是對象里面的數(shù)據(jù)依然是指針復制的,下面我們來看一段代碼:
NSArray *array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"1"],@"2",@"3", nil];
NSArray *arrayCopy = [array copy];
NSArray *arrayMutableCopy = [array mutableCopy];
NSMutableArray *mutableArrayCopy = [array copy];
NSMutableArray *mutableArrayMutableCopy = [array mutableCopy];
NSLog(@"array地址%p arrayCopy地址%p arrayMutableCopy地址%p mutableArrayCopy地址%p mutableArrayCopy地址%p",array,arrayCopy,arrayMutableCopy,mutableArrayCopy,mutableArrayMutableCopy);
NSLog(@"array = %@ arrayCopy = %@ arrayMutableCopy = %@ mutableArrayCopy = %@ mutableArrayCopy = %@",array,arrayCopy,arrayMutableCopy,mutableArrayCopy,mutableArrayMutableCopy);
NSMutableString *mustr = array[0];
[mustr appendString:@"2"];
NSLog(@"array地址%p arrayCopy地址%p arrayMutableCopy地址%p mutableArrayCopy地址%p mutableArrayCopy地址%p",array,arrayCopy,arrayMutableCopy,mutableArrayCopy,mutableArrayMutableCopy);
NSLog(@"array = %@ arrayCopy = %@ arrayMutableCopy = %@ mutableArrayCopy = %@ mutableArrayCopy = %@",array,arrayCopy,arrayMutableCopy,mutableArrayCopy,mutableArrayMutableCopy);
輸出結果:
未更改數(shù)組里面內(nèi)容前的結果:
更改數(shù)組里面的內(nèi)容的輸出結果:
可以看到當更改原數(shù)組的值之后,所有新數(shù)組的值都更改了承冰,即使調(diào)用了MutableCopy方法創(chuàng)建的新數(shù)組里面的值也因此更改华弓,所以可以看出對于系統(tǒng)容器類對象,其元素對象始終是指針復制困乒。