NSString為何要用copy?而不是strong?
strong和retain同義, weak和assign同義, 為什麼要採用這種說法, 似乎是ARC出現後為了消除引用計數的觀念而採用的做法. 至於為什麼要用copy, 由於純NSString是只讀的, 所以strong和copy的結果一樣,據stackOverflow上的說法,是為了防止mutable string被無意中修改, NSMutableString是NSString的子類, 因此NSString指針可以持有NSMutableString對象.
很簡單,假如有一個NSMutableString,現在用他給一個retain修飾 NSString賦值,那麼只是將NSString指向了NSMutableString所指向的位置,並對NSMUtbaleString計數器加一,此時,如果對NSMutableString進行修改,也會導致NSString的值修改,原則上這是不允許的. 如果是copy修飾的NSString對象,在用NSMutableString給他賦值時,會進行深拷貝,及把內容也給拷貝了一份,兩者指向不同的位置,即使改變了NSMutableString的值,NSString的值也不會改變.
所以用copy是為了安全,防止NSMutableString賦值給NSString時,前者修改引起後者值變化而用的.
我這樣說你就明白了 A-&>B A中的一個MutableString給B中的一個Property(NSString類型)賦值 首先是能接受的,父類可以接受子類,如果是retain,僅僅是生成一個指針,計數器加一,然後指向那個MutableString。如果MString改變,B中那個跟著改變,因為是同一塊內存區域。而選擇Copy相當於又生成了一個NSString,與A中的MutableString獨立。
原答案說的並不是那麼清晰,我想通過一個最簡單的例子來說明它們的區別:
首先我們來看看使用strong會出現什麼樣的情況:
.h
@property (nonatomic, strong) NSString *name;
.m
NSMutableString *mStr = [NSMutableString stringWithString:@"張三"];
self.name = mStr;
NSLog(@"使用strong第一次得到的名字:%@", self.name);
[mStr appendString:@"豐"];
NSLog(@"使用strong第二次得到的名字:%@", self.name);
列印結果:
2017-04-07 16:20:10.138793 copyTest[2421:682898] 使用strong第一次得到的名字:張三
2017-04-07 16:20:10.138884 copyTest[2421:682898] 使用strong第二次得到的名字:張三丰
結論:
通過上面的例子我們可以看出,我們在沒有直接修改 self.name 的情況下 self.name 卻被修改了,就好像一個人的名字怎麼能沒有經過自己同意就被修改呢?我們的初衷只是想修改mStr,但是 self.name 卻被意外的修改了,而這就是我們使用strong所不想看到的,它會破壞程序的封裝性。(使用strong後 self.name 和 mStr 指向的是同一片內存,所以修改其中一個值後兩個值就都變了)
那麼使用copy又會得到什麼結果呢?下面是使用copy的例子:
.h
@property (nonatomic, copy) NSString *name;
.m
NSMutableString *mStr = [NSMutableString stringWithString:@"張三"];
self.name = mStr;
NSLog(@"使用copy第一次得到的名字:%@", self.name);
[mStr appendString:@"豐"];
NSLog(@"使用copy第二次得到的名字:%@", self.name);
列印結果:
2017-04-07 16:35:04.012589 copyTest[2428:685221] 使用copy第一次得到的名字:張三
2017-04-07 16:35:04.012676 copyTest[2428:685221] 使用copy第二次得到的名字:張三
結論:
這個例子中我們使用了copy修飾,mStr通過copy得到了一個新的對象賦值給 self.name 這樣我們再修改mStr就跟 self.name 沒關係了,只有直接對 self.name 進行賦值才能改變它的值,這樣就保證了程序的封裝性。
為什麼使用copy而不是strong以上只是一個例子,還有很多情況可以自己去試試,並且可以把屬性類型改成NSMutableString進行不同情況的研究,也可以更加深入理解深拷貝和淺拷貝的含義。
這主要是為了防止NSString被修改。當NSString的賦值來源也是NSString時,strong和copy的作用相同,都是給複製來源的引用計數加1;當NSStrig的賦值來源是NSMutableString時,copy會做深拷貝,即重新生成一個新的對象,修改賦值來源不會影響NSString的值。PS:剛開始測試的時候,對NSString對象賦值我用的_string而不是self.string,結果列印出來的地址一直不變,都是賦值來源的地址。後來才發現copy屬性對對對象拷貝發生在setString:方法里,(⊙﹏⊙)b
因為他是immutable
NSString本身是無所謂的,但是如果一個 NSString 指針指向了一個 NSMutableString的內存空間的話,如果使用 strong 修飾的話,如果你在別處修改這個值的話,那麼原來的值也會改變。用 copy 是生成了一份新的內存空間,所以原值不會改變
http://blog.csdn.net/itianyi/article/details/9018567
這裡寫的很深入 看一下就懂了置頂的答案雖然缺乏自信,但是說的還是沒問題的
就是C指針的原理吧!給指針變數賦了一個地址,通過修改*指針變數,間接修改了那個地址下對應的值吧!
IOS里簡單說就是,數字和字元串本身設為不可變。別人想用,可以,拿我副本用,但是拿我副本用的時候會支會我本體一聲讓我知道你在用(本體引用計數依然+1)。最後本體銷毀的時候,副本一同銷毀。[若我理解有錯煩請大牛指出!]
不過我有個疑問,拷貝出來的分身應該要協同本體一起銷毀,那分身和本體之間應有何種聯繫?
copy會重新生成一個string,被copy的對象發生改變時,copy後的對象不改變
strong僅僅進行強引用確保持有string的對象在生存期間這個string不會被釋放題主說的問題有點問題,應該是NSString用copy或strong都可以,下面分場景說:- 必須使用copy的場景:A對象持有string記做A.string,然後賦值給B對象,記做B.string,若希望B.string的內容改變時A.string不改變就必須用copy
- 必須用strong的場景:若希望B.string的內容改變時同時A.string也改變則必須用strong
- 隨便用哪個的場景:string的內容不會被改變的情況下
It is common practice in Objective-C code to copy value objects—objects that represent attributes.
如果不想深入研究,記住上面這句就好了。
推薦閱讀:
※敢吃的 iOS 客戶端如何做到上線第一天衝到美食分類第一的?
※如何加強 iOS 里的列表滾動時的順暢感?
※是不是 iOS 代碼手寫界面布局已經被判了死緩?
※遊戲開發中的一個小問題(設計模式)?