NSString我們必不可少的類,但是在你@property的時候,到底是用Strong失球,還是Copy修飾岖是。你用對了嗎?
用例子來說明一下
先使用NSString
@property (nonatomic, strong) NSString *strongStr;
@property (nonatomic, copy) NSString *copyedStr;
//不可以寫成copyStr會報property follows cocoa naming convention for returning 'owned' objects
//意思是不能使用copy來作為開頭命名实苞,copy是cocoa用的
這里聲明了兩個NSString變量豺撑,一個用strong修飾,另一個用copy來修飾黔牵,下面我們來用一個NSString對兩個string賦值聪轿。
輸出查看一下結果
NSString *testStr = [NSString stringWithFormat:@"nanshanyi"];
self.strongStr = testStr;
self.copyedStr = testStr;
NSLog(@"testStr: %p, %p",testStr,&testStr);
NSLog(@"strongStr: %p, %p",_strongStr,&_strongStr);
NSLog(@"copyedStr: %p, %p",_copyedStr,&_copyedStr);
//前面的是內存地址,后面的是指針地址
testStr: 0xa01c06542cac2d0a, 0x16fdb1f48
strongStr: 0xa01c06542cac2d0a, 0x1346e6030
copyedStr: 0xa01c06542cac2d0a, 0x1346e6038
根據輸出的內存地址猾浦,我們發(fā)現陆错,不管用的是strong還是copy灯抛,指向的都是同一個地址,也就是testStr的地址音瓷。strongStr和copyedStr都只是對testStr的引用对嚼,只會導致testStr的計數器加1,并沒有拷貝一份新的绳慎,testStr的retainCount應該是3纵竖。
下面我們改用NSMutableString
NSMutableString *testStr = [NSMutableString stringWithFormat:@"nanshanyi"];
self.strongStr = testStr;
self.copyedStr = testStr;
NSLog(@"testStr: %p, %p",testStr,&testStr);
NSLog(@"strongStr: %p, %p",_strongStr,&_strongStr);
NSLog(@"copyedStr: %p, %p",_copyedStr,&_copyedStr);
[testStr appendString:@"123"];//修改一下
NSLog(@"testStr: %@, %p",testStr,&testStr);
NSLog(@"strongStr: %@, %p",_strongStr,&_strongStr);
NSLog(@"copyedStr: %@, %p",_copyedStr,&_copyedStr);
我們再來看一下結果:
testStr: 0x15cdf87f0, 0x16fd99f48
strongStr: 0x15cdf87f0, 0x15cdf3ad0
copyedStr: 0xa0b20b31520b9419, 0x15cdf3ad8
//修改后輸出一下字符串內容
testStr: nanshanyi123, 0x16fd99f48
strongStr: nanshanyi123, 0x15cdf3ad0
copyedStr: nanshanyi, 0x15cdf3ad8
可以看到這個時候,copy修飾的copyedStr字符串偷线,已經不再是簡單的引用了磨确,而是拷貝了一個新的,讓copyedStr指向了這個新的地址声邦。此時testStr的retainCount應該是2乏奥。
然后我們把testStr修改一下,后面接上了“123”亥曹,輸出內容會發(fā)現testStr變化后邓了,strongStr會隨之改變。而copyStr則不會隨之變化媳瞪。
總結
由上面的例子可以得出:當原字符串是NSString時骗炉,由于是不可變字符串,所以蛇受,不管是使用strong還是copy修飾句葵,都是指向原來的對象,copy操作只是做了次淺拷貝兢仰。
而當源字符串是NSMutableString時乍丈,strong只是將原字符串的引用計數加1,而copy
則是對原字符串做了次深拷貝把将,從而生成了一個新的對象轻专,并且copy的對象指向這個新的對象。另外需要注意的是察蹲,這個copy屬性對象的類型始終是NSString请垛,而不是NSMutableString,如果想讓拷貝過來的對象是可變的洽议,就需要使mutableCopy宗收。
所以,如果原字符串是NSMutableString的時候亚兄,使用strong只會增加引用計數器混稽。但是copy會執(zhí)行一次深拷貝,會造成不必要的內存浪費。而如果原字符串是NSString時荚坞,copy和strong效果一樣,就不會有這個問題菲盾。
但是颓影,一般我們聲明NSString時,也不會希望它改變懒鉴,所以一般情況下诡挂,建議用copy,這樣可以避免NSMutableString帶來的奇葩錯誤临谱。
順便提一下assign與weak
我們都知道璃俗,assign用來修飾基本數據類型,weak用來修飾OC對象悉默。
其實照理說assign也可以用來修飾對象城豁。但是assign修飾的對象在此對象釋放的時候,指針地址依然存在抄课,不會被置為nil唱星,這就會造成很嚴重的問題,也就是會產生野指針跟磨。但是用weak來修飾的話在對象釋放的時候會把指針置為nil间聊,從而避免野指針的出現。
那你又會問了抵拘,那憑啥基本數據類型就可以使用assign哎榴。這個就又要扯到堆和棧的問題了,基本數據類型一般是被分配到椊┲耄空間尚蝌。而棧是由系統(tǒng)自動管理分配和釋放。就不會造成野指針的問題墩瞳。