詳解iOS的深淺拷貝
前言
OC對(duì)象的三種拷貝方式
OC的對(duì)象拷貝有如下三種方式,很多時(shí)候我們把深復(fù)制和完全復(fù)制混為一談,其他他們是有區(qū)別的,具體如下
淺復(fù)制(shallow copy):在淺復(fù)制操作時(shí),對(duì)于被復(fù)制對(duì)象的每一層都是指針復(fù)制。
深復(fù)制(one-level-deep copy):在深復(fù)制操作時(shí),對(duì)于被復(fù)制對(duì)象,至少有一層是深復(fù)制。
完全復(fù)制(real-deep copy):在完全復(fù)制操作時(shí),對(duì)于被復(fù)制對(duì)象的每一層都是對(duì)象復(fù)制。
兩圖以避之


理解深復(fù)制(mutableCopy)
淺復(fù)制很簡(jiǎn)單,就不演示了,看上面的圖就懂了,只是簡(jiǎn)單的指針拷貝,所以改變?cè)瓕?duì)象或者拷貝后的對(duì)象,都會(huì)影響另外一個(gè)對(duì)象。
從上圖我們可以看到mutableCopy對(duì)于任何對(duì)象都是內(nèi)容復(fù)制,也就是說進(jìn)行了深復(fù)制。
上代碼:
NSMutableArray * dataArray1=[NSMutableArray arrayWithObjects:
[NSMutableString stringWithString:@"1"],
[NSMutableString stringWithString:@"2"],
[NSMutableString stringWithString:@"3"],
[NSMutableString stringWithString:@"4"],
nil
];
NSMutableArray * dataArray2=[NSMutableArray arrayWithObjects:
[NSMutableString stringWithString:@"one"],
[NSMutableString stringWithString:@"two"],
[NSMutableString stringWithString:@"three"],
[NSMutableString stringWithString:@"four"],
dataArray1,
nil
];
NSMutableArray * dataArray3;
NSMutableString * mStr;
dataArray3=[dataArray2 mutableCopy];
mStr = dataArray2[0];
[mStr appendString:@"--ONE"];
NSLog(@"dataArray3:%@",dataArray3);
NSLog(@"dataArray2:%@",dataArray2);
輸出如下:
2016-07-31 17:40:30.702 test1[2113:169774] dataArray3:(
"one--ONE",
two,
three,
four,
(
1,
2,
3,
4
)
)
2016-07-31 17:40:30.703 test1[2113:169774] dataArray2:(
"one--ONE",
two,
three,
four,
(
1,
2,
3,
4
)
)
看上面的輸出,我們發(fā)現(xiàn)我們改變?cè)瓟?shù)組dataArray2,竟然也會(huì)影響深復(fù)制后的dataArray3,不是說好的內(nèi)容復(fù)制嗎,為什么會(huì)這樣?
這里我們來(lái)說說深復(fù)制和完全復(fù)制的區(qū)別。
我們知道深復(fù)制,就是把原有對(duì)象的內(nèi)容直接克隆一份到新對(duì)象,但是這里有一個(gè)坑就是他只會(huì)復(fù)制一層對(duì)象,而不會(huì)復(fù)制第二層甚至更深層次的對(duì)象。
代碼dataArray3=[dataArray2 mutableCopy];只是對(duì)數(shù)組dataArray2本身進(jìn)行了內(nèi)容拷貝,但是里面的字符串對(duì)象卻沒有進(jìn)行內(nèi)容拷貝,而是進(jìn)行的淺復(fù)制,那么dataArray2和dataArray3里面的對(duì)象是共享同一份的。所以才會(huì)出現(xiàn)上面的情況。
單層深復(fù)制
那么如何解決上面的問題呢?
可以使用如下代碼
dataArray3=[[NSMutableArray alloc]initWithArray:dataArray2 copyItems:YES];
輸出如下:
2016-07-31 17:45:48.472 test1[2151:173221] dataArray3:(
one,
two,
three,
four,
(
1,
2,
3,
4
)
)
2016-07-31 17:45:48.472 test1[2151:173221] dataArray2:(
"one--ONE",
two,
three,
four,
(
1,
2,
3,
4
)
)
可以看到dataArray3并沒有被改變,但是別高興的太早,我們?cè)賮?lái)改改。
代碼如下:
NSMutableArray * dataArray1=[NSMutableArray arrayWithObjects:
[NSMutableString stringWithString:@"1"],
[NSMutableString stringWithString:@"2"],
[NSMutableString stringWithString:@"3"],
[NSMutableString stringWithString:@"4"],
nil
];
NSMutableArray * dataArray2=[NSMutableArray arrayWithObjects:
[NSMutableString stringWithString:@"one"],
[NSMutableString stringWithString:@"two"],
[NSMutableString stringWithString:@"three"],
[NSMutableString stringWithString:@"four"],
dataArray1,
nil
];
NSMutableArray * dataArray3;
NSMutableString * mStr;
dataArray3=[[NSMutableArray alloc]initWithArray:dataArray2 copyItems:YES];
NSMutableArray *mArr = (NSMutableArray *)dataArray2[4];
mStr = mArr[0];
[mStr appendString:@"--ONE"];
NSLog(@"dataArray3:%@",dataArray3);
NSLog(@"dataArray2:%@",dataArray2);
輸出如下:
2016-07-31 17:47:19.421 test1[2174:174714] dataArray3:(
one,
two,
three,
four,
(
"1--ONE",
2,
3,
4
)
)
2016-07-31 17:47:19.421 test1[2174:174714] dataArray2:(
one,
two,
three,
four,
(
"1--ONE",
2,
3,
4
)
)
可以看到深復(fù)制又失效了,這是因?yàn)?code>dataArray3=[[NSMutableArray alloc]initWithArray:dataArray2 copyItems:YES];僅僅能進(jìn)行一層深復(fù)制,對(duì)于第二層或者更多層的就無(wú)效了,那怎么辦呢?
別急,我們還有大招沒放。
完全復(fù)制
要想對(duì)多層集合對(duì)象進(jìn)行復(fù)制,我們需要進(jìn)行完全復(fù)制,這里可以使用歸檔和接檔。
實(shí)現(xiàn)代碼如下:
dataArray3 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:dataArray2]];
此時(shí)輸出如下:
2016-07-31 17:49:55.561 test1[2202:177163] dataArray3:(
one,
two,
three,
four,
(
1,
2,
3,
4
)
)
2016-07-31 17:49:55.562 test1[2202:177163] dataArray2:(
one,
two,
three,
four,
(
"1--ONE",
2,
3,
4
)
)
可以看到dataArray3沒有被dataArray2的修改影響。
類復(fù)制
說完了對(duì)象的復(fù)制,我們來(lái)看看如何實(shí)現(xiàn)類的復(fù)制,因?yàn)楸容^簡(jiǎn)單,直接放上代碼
定義類復(fù)制
#import <Foundation/Foundation.h> @interface Person : NSObject<NSCopying> @property(strong,nonatomic)NSString *age; @property(strong,nonatomic)NSString *name; @end
#import "Person.h"
@implementation Person
- (id)copyWithZone:(NSZone *)zone
{
Person *person = [[Person allocWithZone:zone] init];
person.age = self.age;
person.name = self.name;
return person;
}
@end
調(diào)用
Person *person = [[Person alloc]init];
person.age = @"dsdsd";
person.name = @"dsdsdddww";
Person *copyPerson = [person copy];
NSLog(@"%@-----%@",copyPerson.age, copyPerson.name);
可以看到copyPerson的兩個(gè)屬性和persona一樣。
@property中的copy關(guān)鍵字
在設(shè)置NSString類型的屬性的時(shí)候,我們最好設(shè)置為copy類型,這樣別人使用我們定義的屬性的時(shí)候,他不管怎么改動(dòng)該屬性的賦值,都不會(huì)影響我們給該屬性賦的值,為什么呢?
下面我們來(lái)看看

如上圖所示,string2的屬性是copy類型,可以看到是無(wú)法被修改的。
因?yàn)榇藭r(shí)string2和copystring的內(nèi)存地址不一樣,修改一個(gè),不會(huì)影響另外一個(gè)。

上圖所示,如果string2的屬性是strong類型,就可以被修改,如下圖所示:
因?yàn)榇藭r(shí)string2和copystring的內(nèi)存地址都是一樣的,修改一個(gè),兩個(gè)就同時(shí)被修改
copy關(guān)鍵字的NSMutableString崩潰

原因:
copy關(guān)鍵字的string的setter方法實(shí)際上是把參數(shù)copy之后再賦值給變量_string,那么此時(shí)變量_string雖然被申明為NSMutableString,但是copy之后,就把 變量_string變成了不可變的NSString類型,所以就會(huì)出現(xiàn)方法報(bào)錯(cuò),提示對(duì)不可變的NSString使用了NSMutableString的方法appendString。
總結(jié)
以上就是iOS的深淺拷貝的詳細(xì)內(nèi)容,希望本文在大家開發(fā)iOS的過程中能有所幫助。
相關(guān)文章
iOS 動(dòng)畫實(shí)戰(zhàn)之釣魚小游戲?qū)嵗a
最近小編做了一個(gè)釣魚小游戲,平時(shí)沒有做過,所以上手有點(diǎn)急躁,不過,最終還是實(shí)現(xiàn)了,下面小編給大家分享iOS 動(dòng)畫實(shí)戰(zhàn)之釣魚小游戲的實(shí)現(xiàn)思路,感興趣的朋友一起看看吧2018-02-02
ios12中遇到的帶input彈窗的錯(cuò)位問題的解決方法
這篇文章主要介紹了ios12中遇到的帶input彈窗的錯(cuò)位問題的解決方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2019-05-05
iOS字體抖動(dòng)動(dòng)畫的實(shí)現(xiàn)代碼
這篇文章主要介紹了iOS字體抖動(dòng)動(dòng)畫的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
iOS開發(fā)中UITableview控件的基本使用及性能優(yōu)化方法
這篇文章主要介紹了iOS開發(fā)中UITableview控件的基本使用及性能優(yōu)化方法,代碼基于傳統(tǒng)的Objective-C,需要的朋友可以參考下2015-12-12
iOS UIBezierPath實(shí)現(xiàn)餅狀圖
這篇文章主要為大家詳細(xì)介紹了iOS UIBezierPath實(shí)現(xiàn)餅狀圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03
iOS開發(fā)中仿Tumblr點(diǎn)贊心破碎動(dòng)畫效果
這篇文章主要介紹了iOS開發(fā)中仿Tumblr點(diǎn)贊心破碎動(dòng)畫效果,本文圖文并茂給大家介紹的非常詳細(xì),需要的朋友可以參考下2017-04-04

