重新理解strong與weak(強引用,弱引用),以及strong和copy的區別
- (void)test:
{
NSMutableString *mStr = [NSMutableStringstringWithFormat:@"hello"];
self.sStr = mStr;
self.cStr = mStr;
NSLog(@"mStr:%p,%p", mStr,&mStr);
NSLog(@"strongStr:%p,%p", _sStr, &_sStr);
NSLog(@"copyStr:%p,%p", _cStr, &_cStr);
}
上段程式碼中sStr與mStr指向同樣的地址,他們指向的是同一個物件@“hello
當把mStr賦值給copy的cStr時,cStr物件是深複製而來,一個新的物件,這個物件有新的地址不再是原來的地址了
如果現在改變mStr的值:
[mStr appendString:@"world"];
NSLog(@"strongStr:%@", _sStr);
NSLog(@"copyStr:%@", _cStr);
結果
使用strong的字串sStr的值:@"helloworld",而使用copy的字串cStr的值:@"hello",
所以,如果一般情況下,我們都不希望字串的值跟著mStr變化,所以我們一般用copy來設定string的屬性。
如果希望字串的值跟著賦值的字串的值變化,可以使用strong,retain。
注意:上面的情況是針對於當把NSMutableString賦值給NSString的時候,才會有不同,如果是賦值是NSString
物件,那麼使用copy還是strong,結果都是一樣的,因為NSString物件根本就不能改變自身的值,他是不可變的。
把一個物件賦值給一個屬性變數,當這個物件變化了,如果希望屬性變數變化就使用strong屬性,如果希望屬性變數不跟著變化,就是用copy屬性。
結論
這裡寫一寫結論引用自別的部落格(http://blog.csdn.net/itianyi/article/details/9018567
對源頭是NSMutableString的字串,retain僅僅是指標引用,增加了引用計數器,這樣源頭改變的時候,用這種retain方式宣告的變數(無論被賦值的變數是可變的還是不可變的),它也會跟著改變;而copy宣告的變數,它不會跟著源頭改變,它實際上是深拷貝。
對源頭是NSString的字串,無論是retain宣告的變數還是copy宣告的變數,當第二次源頭的字串重新指向其它的地方的時候,它還是指向原來的最初的那個位置,也就是說其實二者都是指標引用,也就是淺拷貝。
另外說明一下,這兩者對記憶體計數的影響都是一樣的,都會增加記憶體引用計數,都需要在最後的時候做處理。
其實說白了,對字串為啥要用這兩種方式?我覺得還是一個安全問題,比如宣告的一個NSString *str變數,然後把一個NSMutableString *mStr變數的賦值給它了,如果要求str跟著mStr變化,那麼就用retain;如果str不能跟著mStr一起變化,那就用copy。而對於要把NSString型別的字串賦值給str,那兩都沒啥區別。不會影響安全性,記憶體管理也一樣。