大部分的時(shí)候NSString的屬性都是copy拳喻,那copy與strong的情況下到底有什么區(qū)別呢?
比如:
@property (retain,nonatomic) NSString *rStr;
@property (copy, nonatomic)? NSString *cStr;
- (void)test:
{
NSMutableString *mStr = [NSMutableStringstringWithFormat:@"abc"];
self.rStr? = mStr;
self.cStr? ? = mStr;
NSLog(@"mStr:%p,%p",? mStr,&mStr);
NSLog(@"retainStr:%p,%p", _rStr, &_rStr);
NSLog(@"copyStr:%p,%p",? _cStr, &_cStr);
}
假如燕耿,mStr對象的地址為0x11,也就是0x11是@“abc”的首地址掺栅,mStr變量自身在內(nèi)存中的地址為0x123烙肺;
當(dāng)把mStr賦值給retain的rStr時(shí),rStr對象的地址為0x11氧卧,rStr變量自身在內(nèi)存中的地址為0x124桃笙;rStr與mStr指向同樣的地址,他們指向的是同一個(gè)對象@“abc”沙绝,這個(gè)對象的地址為0x11搏明,所以他們的值是一樣的。
當(dāng)把mStr賦值給copy的cStr時(shí)宿饱,cStr對象的地址為0x22熏瞄,cStr變量自身在內(nèi)存中的地址0x125;cStr與mStr指向的地址是不一樣的谬以,他們指向的是不同的對象强饮,所以copy是深復(fù)制,一個(gè)新的對象为黎,這個(gè)對象的地址為0x22邮丰,值為@“abc”。
如果現(xiàn)在改變mStr的值:
[mStr appendString:@"de"];
NSLog(@"retainStr:%@",? _rStr);
NSLog(@"copyStr:%@",? ? _cStr);
結(jié)果铭乾,
使用retain的字串rStr的值:@"abcde",
而使用copy的字串cStr的值:@"abc",
所以剪廉,如果一般情況下,我們都不希望字串的值跟著mStr變化炕檩,所以我們一般用copy來設(shè)置string的屬性斗蒋。
如果希望字串的值跟著賦值的字串的值變化捌斧,可以使用strong,retain泉沾。
注意:上面的情況是針對于當(dāng)把NSMutableString賦值給NSString的時(shí)候捞蚂,才會有不同,如果是賦值是NSString對象跷究,那么使用copy還是strong姓迅,結(jié)果都是一樣的,因?yàn)镹SString對象根本就不能改變自身的值俊马,他是不可變的丁存。
把一個(gè)對象賦值給一個(gè)屬性變量,當(dāng)這個(gè)對象變化了柴我,如果希望屬性變量變化就使用strong屬性解寝,如果希望屬性變量不跟著變化,就是用copy屬性屯换。
由此可以看出:
對源頭是NSMutableString的字符串编丘,retain僅僅是指針引用与学,增加了引用計(jì)數(shù)器彤悔,這樣源頭改變的時(shí)候,用這種retain方式聲明的變量(無論被賦值的變量是可變的還是不可變的)索守,它也會跟著改變;而copy聲明的變量晕窑,它不會跟著源頭改變,它實(shí)際上是深拷貝卵佛。
對源頭是NSString的字符串杨赤,無論是retain聲明的變量還是copy聲明的變量,當(dāng)?shù)诙卧搭^的字符串重新指向其它的地方的時(shí)候截汪,它還是指向原來的最初的那個(gè)位置疾牲,也就是說其實(shí)二者都是指針引用,也就是淺拷貝衙解。
另外說明一下阳柔,這兩者對內(nèi)存計(jì)數(shù)的影響都是一樣的,都會增加內(nèi)存引用計(jì)數(shù)蚓峦,都需要在最后的時(shí)候做處理舌剂。
其實(shí)說白了,對字符串為啥要用這兩種方式暑椰?我覺得還是一個(gè)安全問題霍转,比如聲明的一個(gè)NSString *str變量,然后把一個(gè)NSMutableString *mStr變量的賦值給它了一汽,如果要求str跟著mStr變化避消,那么就用retain;如果str不能跟著mStr一起變化,那就用copy。而對于要把NSString類型的字符串賦值給str岩喷,那兩都沒啥區(qū)別委造。不會影響安全性,內(nèi)存管理也一樣均驶。