copy那些事兒

1.Copy 和 MutbaleCopy 介紹

2.淺拷貝和深拷貝

3.block為何使用copy挪钓?

4.使用copy的優(yōu)勢

5.總結(jié)


1. Copy和MutbaleCopy介紹

如果我們需要?jiǎng)?chuàng)建一個(gè)對象蒙具,使該對象與源對象的內(nèi)容一致,那么就可以使用到拷貝(copy或mutablecopy)诀姚,下面來看一段簡單的代碼:

NSString* string =@"egg";

[stringcopy];//拷貝出的內(nèi)容為egg的NSString類型字符串

[stringmutableCopy];//拷貝出的內(nèi)容為egg的NSMutableString類型字符串

NSArray* array =@[@"egg"];

[arraycopy];//拷貝出內(nèi)容與array相同的NSArray類型數(shù)組

[arraymutableCopy];//拷貝出內(nèi)容與array相同的NSMutableArray類型數(shù)組

NSDictionary* Goods =@{@"name":@"egg"};

[Goodscopy];//拷貝出內(nèi)容與Goods相同的NSDictionary類型字典

[GoodsmutableCopy];//拷貝出內(nèi)容與Goods相同的NSMutablDictionary類型字典

如注釋所述:

使用copy拷貝出來的對象類型總是不可變類型(例如:NSString,NSArray,NSDictionary等)假哎;

使用mutableCopy拷貝出來的對象類型總是可變類型(例如:NSMutableString,NSMutableArray,NSMutablDictionary等)芒帕;

2. 深拷貝和淺拷貝

網(wǎng)上有很多討論深拷貝淺拷貝的文章歉嗓,有些文章甚至說copy都是淺拷貝mutableCopy都是深拷貝,其實(shí)這種觀點(diǎn)并不絕對正確背蟆。

那何為淺拷貝何為深拷貝呢鉴分?

淺拷貝:拷貝出來的對象與源對象地址一致。簡單說就是如果修改了拷貝對象的值带膀,那么源對象也會(huì)隨之相應(yīng)改變志珍。

深拷貝:拷貝出來的對象與源對象地址不一致。簡單說就是無論如何修改拷貝對象都不會(huì)對源對象產(chǎn)生任何影響垛叨。

為什么說網(wǎng)上那些“copy都是淺拷貝mutableCopy都是深拷貝”的說法說法不準(zhǔn)確呢伦糯,這里就有一種情況不符合它的表述:

當(dāng)使用copy從一個(gè)可變的對象拷貝出來一個(gè)不可變的對象時(shí),這種情況就屬于深拷貝而不是淺拷貝嗽元!NSMutableDictionary* EggGoods = [NSMutableDictionarydictionaryWithObjectsAndKeys:@"name",@"redEgg",nil];NSDictionary* goods1 = [EggGoodscopy];//屬于深拷貝范疇

這里需要留意一下敛纲,其實(shí)深拷貝與淺拷貝也有相對之分。

對于NSString對象剂癌,淺拷貝和深拷貝沒有任何異議淤翔,但是對于容器類對象比如:NSArray,NSDcitionary佩谷,NSSet這些容器類對象旁壮,當(dāng)然淺拷貝依然是淺拷貝(指針拷貝),但是深拷貝就不同了,這里會(huì)有兩種情況谐檀,我們暫時(shí)可以把這種區(qū)別分為不完全深拷貝和完全深拷貝抡谐。

不完全深拷貝:只拷貝容器對象,對于容器內(nèi)部的對象只保存一份引用(拷貝了一個(gè)外殼兒)桐猬;

完全深拷貝:連同容器內(nèi)部的對象完全拷貝一份出來麦撵;

這種區(qū)分可以參照下圖:

修改copyarr1不會(huì)影響到arr1,但如果通過copyarr1修改數(shù)組內(nèi)的obj,對應(yīng)的源arr1內(nèi)的obj也會(huì)隨之改變课幕。

無論是修改copyarr2厦坛,還是通過copyarr2修改數(shù)組內(nèi)部的obj五垮,對源arr2都沒有任何影響乍惊。

通常默認(rèn)狀態(tài)下深拷貝指的是不完全深拷貝,如果想實(shí)現(xiàn)完全深拷貝放仗,需要自己重寫copyWithZone:方法润绎。給一段筆者調(diào)試的代碼看下吧:

// Egg

- (id)copyWithZone:(NSZone*)zone {

Egg* egg = [[EggallocWithZone:zone]init];

egg.name=self.name;

egg.weight=self.weight;

returnegg;

}

//完全深拷貝測試code

Egg* egg1 = [[Eggalloc]init];

Egg* egg2 = [[Eggalloc]init];

NSArray* arr1 =@[egg1,egg2];

NSArray* copyarr1 = [arr1copy];

NSLog(@"------->源數(shù)據(jù):%@/n拷貝數(shù)據(jù):%@",arr1,copyarr1);

這樣就簡單實(shí)現(xiàn)了完全深拷貝。(蘋果官方文檔說copy方法內(nèi)部默認(rèn)會(huì)調(diào)用copyWithZone:方法,但是NSArray執(zhí)行copy時(shí)并沒有調(diào)用它莉撇,按照官方文檔可能是OC已經(jīng)棄用了zone概念呢蛤,當(dāng)然可以利用分類重寫copy方法來解決)。

3. 很多時(shí)候使用block會(huì)用copy來修飾棍郎,為什么呢其障?

block通常會(huì)作為對象被使用,所以block理論上是可以retain或release的涂佃,特殊之處在于創(chuàng)建block的時(shí)候它的內(nèi)存是默認(rèn)分配在棧上而不是堆上励翼,這就決定了block的作用域僅限于當(dāng)前上下文,在該作用域之外的地方調(diào)用這個(gè)block辜荠,程序就會(huì)carsh汽抚。

之所以使用copy來修飾block,是因?yàn)閏opy將block從內(nèi)存棧區(qū)移到了堆區(qū),這樣就可以在block定義域之外有調(diào)用需求的地方來安全的調(diào)用它伯病。其實(shí)ARC環(huán)境下使用copy與strong都一樣造烁,因?yàn)閎lock的retain就是用copy來實(shí)現(xiàn)的,習(xí)慣用copy的程序員可能像筆者一樣是一路從MRC走來的午笛。

4. 使用copy的優(yōu)勢

相對于直接使用賦值語句惭蟋,使用copy來處理數(shù)據(jù)有時(shí)候可以避免與OC的多態(tài)性產(chǎn)生沖突,帶來不必要的維護(hù)成本開銷药磺。

看一段代碼:

打印信息

-------> Arr:(

"redegg!",

"blueegg!"

) , array:(

"redegg!",

"blueegg!"

)

這里明明看到可變數(shù)組添加對象是在賦值語句之后敞葛,但從打印看到,后添加的對象還會(huì)影響到不可變數(shù)組呢与涡?原因就是OC支持多態(tài)惹谐,表面上Arr是NSArray類型,其實(shí)骨子里是NSMutableArray對象驼卖。這種問題在排查調(diào)試的時(shí)候去分析就比較困難了氨肌。

那使用copy再來看下

打印信息

-------> Arr:(

"redegg!"

) , array:(

"redegg!",

"blueegg!"

)

這里使用copy可以保證無論賦值的是可變還是不可變數(shù)組,NSArray都不會(huì)再變酌畜。這也是為什么大多數(shù)時(shí)候NSString,NSArray,NSDictionary屬性用copy而不用strong修飾的原因怎囚。

總結(jié):網(wǎng)上也有很多寫的很好的關(guān)于copy和mutableCopy用法的總結(jié),筆者這里就不在贅述了,至于開發(fā)過程中遇到這方面的問題桥胞,只要細(xì)心一些恳守,按照用法規(guī)則多調(diào)試,都能夠解決贩虾。所提之處如有錯(cuò)誤催烘,歡迎大家指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缎罢,一起剝皮案震驚了整個(gè)濱河市伊群,隨后出現(xiàn)的幾起案子考杉,更是在濱河造成了極大的恐慌,老刑警劉巖舰始,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件崇棠,死亡現(xiàn)場離奇詭異,居然都是意外死亡丸卷,警方通過查閱死者的電腦和手機(jī)枕稀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谜嫉,“玉大人抽莱,你說我怎么就攤上這事〗径瘢” “怎么了食铐?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長僧鲁。 經(jīng)常有香客問我虐呻,道長,這世上最難降的妖魔是什么寞秃? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任斟叼,我火速辦了婚禮,結(jié)果婚禮上春寿,老公的妹妹穿的比我還像新娘朗涩。我一直安慰自己,他們只是感情好绑改,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布谢床。 她就那樣靜靜地躺著,像睡著了一般厘线。 火紅的嫁衣襯著肌膚如雪识腿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天造壮,我揣著相機(jī)與錄音渡讼,去河邊找鬼。 笑死耳璧,一個(gè)胖子當(dāng)著我的面吹牛成箫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播旨枯,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼蹬昌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了召廷?” 一聲冷哼從身側(cè)響起凳厢,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤账胧,失蹤者是張志新(化名)和其女友劉穎竞慢,沒想到半個(gè)月后先紫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡筹煮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年遮精,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片败潦。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡本冲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出劫扒,到底是詐尸還是另有隱情檬洞,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布沟饥,位于F島的核電站添怔,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏贤旷。R本人自食惡果不足惜广料,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望幼驶。 院中可真熱鬧艾杏,春花似錦、人聲如沸盅藻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽氏淑。三九已至其兴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間夸政,已是汗流浹背元旬。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留守问,地道東北人匀归。 一個(gè)月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像耗帕,于是被迫代替她去往敵國和親穆端。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容