copy 與 mutablecopy

相信對于有一定iOS開發(fā)經驗的同學來說痘绎,對于copy關鍵字一定不陌生泉哈,從字義上來看蛉幸,應該就是復制一個對象,然后我們對于NSString類型的屬性丛晦,一般也用copy關鍵字奕纫。但是大家對于copy關鍵字真正有什么具體了解呢,什么時候用copy烫沙,什么時候用mutableCopy匹层,區(qū)別又在哪里,對于內存存儲上又有什么知識點锌蓄,我相信還有一部分同學一知半解又固。秉著鉆研探索的精神仲器,我們來詳細的學習一下煤率。

首先我們先說兩個兩個概念:

淺復制:不拷貝對象本身仰冠,僅僅是拷貝指向對象的指針
深復制:是直接拷貝整個對象內存到另一塊內存中

[圖片上傳失敗...(image-9e68bd-1524395644405)]

一般來說像這種使用‘=’號賦值的對象,基本上都是淺復制

   UIView * view1 = [[UIView alloc]init];
   UIView * view2 = [[UIView alloc]init];
   view1 = view2;

[圖片上傳失敗...(image-769ab5-1524395644405)]

內存地址一樣的蝶糯,很簡單洋只,所以它也是我們說的淺復制之一。

然后我們來來看copy這關鍵字昼捍;

copy的字面意思就是“復制”识虚,它是產生一個副本的過程,再來看在iOS里妒茬,copy與mutableCopy都是NSObject里的方法担锤,一個NSObject的對象要想使用這兩個函數,那么類必須實現(xiàn)NSCopying協(xié)議或NSMutableCopying協(xié)議乍钻,并且是實現(xiàn)了一般來說我們用的很多系統(tǒng)里的容器類已經實現(xiàn)了這些方法肛循。

[圖片上傳失敗...(image-20e23a-1524395644405)]

如果不遵守協(xié)議,直接使用[xxx copy]银择,那么會直接導致程序崩潰多糠,比如UIView這個類就不允許使用copy

'NSInvalidArgumentException', reason: '-[UIView copyWithZone:]: unrecognized selector sent to instance 0x7fd5605099f0'
*** First throw call stack:
some error....

然后我們再來看copy關鍵字的特點:
修改源對象的屬性和行為,不會影響副本對象
修改副本對象的屬性和行為浩考,不會影響源對象
一個對象可以通過copy和mutableCopy方法來創(chuàng)建一個副本對象
copy:創(chuàng)建的是不可變副本(NSString夹孔,NSArray,NSDictionary)
mutableCopy:創(chuàng)建的是可變副本(NSMutableString析孽,NSMutableArray搭伤,NSMutableDictionary)

原則就是:修改新(舊)對象,不影響舊(新)對象袜瞬!而且不一定產生新的對象A(劃重點)

看個例子:

   NSString * str = @"testStr";
   NSMutableString * mutableStr = [str mutableCopy];
   NSLog(@"%@,%p",str,str);
   NSLog(@"%@,%p",mutableStr,mutableStr);

打印

testStr,0x103b9f068
testStr,0x600000264d80

可以看到兩個對象的內容完全一樣,但是地址空間變了吞滞,說明開辟了一塊新內存供給副本佑菩,為什么這個會產生新的對象呢?
1.因為原則 修改新(舊)對象裁赠,不影響舊(新)對象殿漠,所以生成一個新的對象
2.因為以前的對象是個不可變對象,而通過mutableCopy拷貝出來的對象必須是一個可變的對象佩捞,所以必須生成一個新的對象

同理:

NSMutableString * mutableStr = [NSMutableString stringWithFormat:@"mutableStr"];
NSMutableString * str = [mutableStr mutableCopy];
[str appendString:@"123"];
NSLog(@"%@,%p",mutableStr,mutableStr);
NSLog(@"%@,%p",str,str);

打印

mutableStr,0x6080000778c0
mutableStr123,0x608000077bc0

文字內容不同绞幌,對象地址不同,修改新(舊)對象一忱,不影響舊(新)對象

相同的

  NSMutableString * mutableStr = [NSMutableString stringWithFormat:@"mutableStr"];
  NSString * str = [mutableStr copy];
  NSLog(@"%@,%p",mutableStr,mutableStr);
  NSLog(@"%@,%p",str,str);

打印

mutableStr,0x600000075900
mutableStr,0x600000035360

原理一樣莲蜘,使用copy關鍵字谭确,產生了一個新的不可變的對象

以上的例子我們可以發(fā)先,使用copy或者mutableCopy都有產生新對象票渠,現(xiàn)在我們再來看一個例子

 NSString * str = @"str";
 NSString * copyStr = [str copy];
 NSLog(@"%@,%p",str,str);
 NSLog(@"%@,%p",copyStr,copyStr);

打印

str,0x10c65e068
str,0x10c65e068

這下我們發(fā)現(xiàn)逐哈,兩個對象的內存地址完全一樣,所以系統(tǒng)并沒有創(chuàng)建一個新對象问顷,這是為什么呢昂秃?
當我們對一個不可變對象(NSString類型)使用copy關鍵字的時候,系統(tǒng)是不會產生一個新對象杜窄,因為原來的對象是不能修改的肠骆,拷貝出來的對象也是不能修改的,那么既然兩個都不可以修改塞耕,所以這兩個對象永遠也不會影響到另一個對象(符合我們說的“修改新(舊)對象蚀腿,不影響舊(新)對象”原則),系統(tǒng)為了節(jié)省內存扫外,所以就不會產生一個新的對象了莉钙。

那么問題來了, copy到底是深拷貝還是淺拷貝畏浆?
我相信有的同學認為只要是使用copy關鍵字胆胰,那么肯定都是深拷貝,這樣是很不嚴謹的刻获,就比如上個例子蜀涨,雖然使用了copy,但是指針地址是一樣蝎毡,那么它就應該是淺拷貝厚柳。
所以是否是深淺拷貝,是否創(chuàng)建新的對象沐兵,是由程序運行的環(huán)境所造成的别垮,并不是一概而論。

對于NSArray扎谎,NSDictionary碳想,道理也是相同的。

現(xiàn)在再讓我們看下copy的內存管理:

淺拷貝不會生成新的對象毁靶,所以系統(tǒng)會對以前的對象進行一次retain胧奔,深拷貝會產生新的對象,系統(tǒng)不會對以前的對象進行retain预吆。

接著我們來看下copy與Block的配合使用

首先我們還是回顧一個概念

block默認存儲在棧中龙填,棧中的Block訪問到的外界對象,不會對應進行retain
block如果在堆中,在block中訪問了外界的對象岩遗,會對外界的對象進行一次retian

因為block在什么時候執(zhí)行是不確定的扇商,所以如果block里外部對象被提前釋放了,那么如果這時候block執(zhí)行了宿礁,造成野指針異常案铺,程序crash。

所以對于Block來說窘拯,我們一般都用copy關鍵字修飾.

#import <Foundation/Foundation.h>

typedef void(^TestBlock)(NSString * str);

@interface Model : NSObject

@property (nonatomic,copy) TestBlock testblock;

@end

使用copy保存block红且,這樣可以保住block中,避免以后調用block的時候涤姊,外界的對象已經釋放了

作者:司機王
鏈接:http://www.reibang.com/p/700f58eb0b86
來源:簡書
著作權歸作者所有。商業(yè)轉載請聯(lián)系作者獲得授權嗤放,非商業(yè)轉載請注明出處思喊。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市次酌,隨后出現(xiàn)的幾起案子恨课,更是在濱河造成了極大的恐慌,老刑警劉巖岳服,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件剂公,死亡現(xiàn)場離奇詭異,居然都是意外死亡吊宋,警方通過查閱死者的電腦和手機纲辽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來璃搜,“玉大人拖吼,你說我怎么就攤上這事≌馕牵” “怎么了吊档?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長唾糯。 經常有香客問我怠硼,道長,這世上最難降的妖魔是什么移怯? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任香璃,我火速辦了婚禮,結果婚禮上芋酌,老公的妹妹穿的比我還像新娘增显。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布同云。 她就那樣靜靜地躺著糖权,像睡著了一般。 火紅的嫁衣襯著肌膚如雪炸站。 梳的紋絲不亂的頭發(fā)上星澳,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天,我揣著相機與錄音旱易,去河邊找鬼禁偎。 笑死,一個胖子當著我的面吹牛阀坏,可吹牛的內容都是我干的如暖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼忌堂,長吁一口氣:“原來是場噩夢啊……” “哼盒至!你這毒婦竟也來了?” 一聲冷哼從身側響起士修,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤枷遂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后棋嘲,有當地人在樹林里發(fā)現(xiàn)了一具尸體酒唉,經...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年沸移,在試婚紗的時候發(fā)現(xiàn)自己被綠了痪伦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡阔籽,死狀恐怖流妻,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情笆制,我是刑警寧澤绅这,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站在辆,受9級特大地震影響证薇,放射性物質發(fā)生泄漏。R本人自食惡果不足惜匆篓,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一浑度、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鸦概,春花似錦箩张、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽饮笛。三九已至,卻和暖如春论熙,著一層夾襖步出監(jiān)牢的瞬間福青,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工脓诡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留无午,地道東北人。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓祝谚,卻偏偏與公主長得像宪迟,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子踊跟,可洞房花燭夜當晚...
    茶點故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內容