對iOS淺拷貝、深拷貝的理解

做iOS開發(fā)的需要學習內存管理躬翁,有一些概念在工作和面試中常常遇到:什么是深拷貝焦蘑,什么是淺拷貝? mutableCopycopy有什么區(qū)別盒发? 為啥NSString通常是copy?感覺網(wǎng)上一些資料講的不是很清楚狡逢,這里說明幾點:

1. 什么是淺拷貝宁舰、深拷貝?

A: 簡單理解就是奢浑,淺拷貝是拷貝了指向對象的指針蛮艰, 深拷貝不但拷貝了對象的指針,還在系統(tǒng)中再分配一塊內存雀彼,存放拷貝對象的內容壤蚜。

2. 如何判斷淺拷貝、深拷貝徊哑?

A: 深淺拷貝取決于拷貝后的對象的是不是和被拷貝對象的地址相同袜刷,如果不同,則產(chǎn)生了新的對象莺丑,則執(zhí)行的是深拷貝著蟹,如果相同,則只是指針拷貝梢莽,相當于retain一次原對象, 執(zhí)行的是淺拷貝.

舉個栗子??

Snip20170324_2.png

深切拷貝取決于是否為對象分配了新的內存地址萧豆,否則就是指針Copy.

此處上碼:

    NSString *str1 = [NSString string];
    NSArray *arr1 = [NSArray array];
    
    NSMutableString *mStr1 = [NSMutableString string];
    NSMutableArray *mArr1 = [NSMutableArray array];
    
    NSLog(@"-------------這是淺拷貝---未產(chǎn)生新對象----------\n\n");
    NSLog(@"-------------不可變對象使用copy------------");
    NSString *testStr1 = [str1 copy];
    NSArray *testArr1 = [arr1 copy];
    NSLog(@"str1: %p, testStr1 : %p", str1, testStr1);
    NSLog(@"arr1: %p, testArr1 : %p", arr1, testArr1);
    NSLog(@"\n\n");

    NSLog(@"-------------這是深拷貝---產(chǎn)生了新對象----------\n\n");
    NSLog(@"-----------不可變對象使用mutableCopy----------");
    NSMutableString *testmStr1 = [str1 mutableCopy];
    NSMutableArray *testmArr1 = [arr1 mutableCopy];
    NSLog(@"str1: %p, testmStr1 : %p", str1, testmStr1);
    NSLog(@"arr1: %p, testmArr1 : %p", arr1, testmArr1);

    NSLog(@"-------------可變對象使用copy-------------");
    NSString *testStr2 = [mStr1 copy];
    NSArray *testArr2 = [mArr1 copy];
    NSLog(@"mStr1: %p, testStr2 : %p", mStr1, testStr2);
    NSLog(@"mArr1: %p, testArr2 : %p", mArr1, testArr2);
    
    NSLog(@"-------------可變對象使用mutableCopy-----------");
    NSMutableString *testmStr2 = [mStr1 mutableCopy];
    NSMutableArray *testmArr2 = [mArr1 mutableCopy];
    NSLog(@"mStr1: %p, testmStr2 : %p", mStr1, testmStr2);
    NSLog(@"mArr1: %p, testmArr2 : %p", mArr1, testmArr2);

運行結果:

深淺拷貝1.png

其實常用的Foundation框架類型,比如NSString,淺拷貝昏名,也就是木有產(chǎn)生新對象的情況涮雷,只有一種,就是不可變對象使用copy操作轻局,借用網(wǎng)上的一張圖:

深淺拷貝2.jpg

其他的比如NSArray洪鸭、NSDictionary類似样刷,可以參考 漢斯哈哈哈的文章

3. 為啥NSString通常用copy?什么時候用strong?

A: 因為在使用NSString的時候卿嘲,一般如果初始化后不想改變這個NSString的值颂斜,應該將其類型設為copy,如果用strong類型拾枣,比如NSStringNSMutableString賦值沃疮,指向其地址,當NSMutableString的值被改變時梅肤,這個NSString值也發(fā)生了變化司蔬,如果是copy修飾的NSString對象,在用NSMutableString給他賦值時,會進行深拷貝,即把其內容也給拷貝了一份,兩者指向不同的位置,即使改變了NSMutableString的值,NSString的值也不會改變.

參考stackoverflow的問題 NSString property: copy or retain?
Youtube上一個很不錯的視頻說明了這個問題:Why you might use copy instead of strong in an Objective-c @property

上碼:

@property (nonatomic, strong) NSString *aStrongStr;
@property (nonatomic, copy) NSString *aCopyStr;
    NSMutableString *mStr = [NSMutableString stringWithString:@"hello"];
    self.aStrongStr = mStr;
    self.aCopyStr = mStr;
    NSLog(@"self.aStrongStr = %@", self.aStrongStr);
    NSLog(@"self.aCopyStr = %@", self.aCopyStr);
    
    [mStr appendString:@" world!"];
    NSLog(@"self.aStrongStr = %@", self.aStrongStr);
    NSLog(@"self.aCopyStr = %@", self.aCopyStr);
NSString定義copy.png

4. 還需要注意一點,mutableCopy返回的是可變對象姨蝴,copy返回的是不可變對象俊啼。

NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithObjects:@1, @2, nil];
 NSMutableArray *array = [mutableArray copy]; 
[array addObject:@3];

雖然array定義的是NSMutableArray, 其實是copy方法返回的一個不可變的數(shù)組,所以在執(zhí)行addObject的方法會報錯左医。

問題:NSString什么時候用copy授帕,什么時候用strong

引用一篇文章: NSString什么時候用copy,什么時候用strong

把一個對象賦值給一個屬性變量浮梢,當這個對象變化了跛十,如果希望屬性變量變化就使用strong屬性,如果希望屬性變量不跟著變化秕硝,就是用copy屬性芥映。

所以,如果一般情況下远豺,我們都不希望字串的值跟著NSMutableString變化奈偏,所以我們一般用copy來設置string的屬性。
如果希望字串的值跟著賦值的字串的值變化躯护,可以使用strong
注意:上面的情況是針對于當把 NSMutableString賦值給NSString的時候惊来,才會有不同,如果是賦值是NSString對象榛做,那么使用copy還是strong唁盏,結果都是一樣的,因為NSString對象根本就不能改變自身的值检眯,他是不可變的厘擂。

結論

在集合類對象中,對immutable對象進行copy锰瘸,是指針復制刽严,mutableCopy是內容復制;對mutable對象進行copy和mutableCopy都是內容復制。但是:集合對象的內容復制僅限于對象本身舞萄,對象元素仍然是指針復制眨补。用代碼簡單表示如下:

[immutableObject copy] // 淺復制
[immutableObject mutableCopy] //單層深復制
[mutableObject copy] //單層深復制
[mutableObject mutableCopy] //單層深復制

參考:

  1. NSString什么時候用copy,什么時候用strong
  2. NSString屬性什么時候用copy倒脓,什么時候用strong?
  3. NSString特性分析學習
  4. iOSInterviewQuestions/《招聘一個靠譜的iOS》面試題參考答案(上).md at master · ChenYilong/iOSInterviewQuestions

如果有誤撑螺,歡迎拍磚~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市崎弃,隨后出現(xiàn)的幾起案子甘晤,更是在濱河造成了極大的恐慌,老刑警劉巖饲做,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件线婚,死亡現(xiàn)場離奇詭異,居然都是意外死亡盆均,警方通過查閱死者的電腦和手機塞弊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來泪姨,“玉大人游沿,你說我怎么就攤上這事“估” “怎么了奏候?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長唇敞。 經(jīng)常有香客問我,道長咒彤,這世上最難降的妖魔是什么疆柔? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮镶柱,結果婚禮上旷档,老公的妹妹穿的比我還像新娘。我一直安慰自己歇拆,他們只是感情好鞋屈,可當我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著故觅,像睡著了一般厂庇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上输吏,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天权旷,我揣著相機與錄音,去河邊找鬼贯溅。 笑死拄氯,一個胖子當著我的面吹牛躲查,可吹牛的內容都是我干的。 我是一名探鬼主播译柏,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼镣煮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了鄙麦?” 一聲冷哼從身側響起典唇,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎黔衡,沒想到半個月后蚓聘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡盟劫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年夜牡,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片侣签。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡塘装,死狀恐怖,靈堂內的尸體忽然破棺而出影所,到底是詐尸還是另有隱情蹦肴,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布猴娩,位于F島的核電站阴幌,受9級特大地震影響,放射性物質發(fā)生泄漏卷中。R本人自食惡果不足惜矛双,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蟆豫。 院中可真熱鬧议忽,春花似錦、人聲如沸十减。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽帮辟。三九已至速址,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間织阅,已是汗流浹背壳繁。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人闹炉。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓蒿赢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親渣触。 傳聞我的和親對象是個殘疾皇子羡棵,可洞房花燭夜當晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內容