1.首先定義兩個屬性
@property (nonatomic,strong)NSString *strongStr;
@property (nonatomic,copy )NSString *copyssStr;
2.然後聲明一個不可變的NSSring對象,給這兩個屬性對象賦值,分別輸出他們的指針和內存地址。
- (void)test{
NSString *string = [NSStringstringWithFormat:@"測試文字"];//註釋1
self.strongStr = string;
self.copyssStr = string;
NSLog(@"測試文字 String: %p, %p", string, &string);
NSLog(@"Strong屬性 String: %p, %p",_strongStr, &_strongStr);
NSLog(@"Copy 屬性 String: %p, %p",_copyssStr, &_copyssStr);
}
輸出如下:
2017-08-10 15:37:57.409 text[58755:1219627] 測試文字 String: 0x7ae904f0, 0xbffd80ac
2017-08-10 15:37:57.409 text[58755:1219627] Strong屬性 String: 0x7ae904f0, 0x7cc820f0
2017-08-10 15:37:57.410 text[58755:1219627] Copy 屬性 String: 0x7ae904f0, 0x7cc820f4
(lldb)
結果表明:不管是Strong還是Copy屬性的對象,指向的地址都是同一個原來String指向的地址。
如在MRC環境,輸出String的引用計數,會看到其引用計數值是3,即Strong操作和Copy操作都會使原字符串對象的引用計數值加了1。
3.接着再聲明一個可變的NSSring對象,給這兩個屬性對象賦值,分別輸出他們的指針和內存地址。
只替換註釋1 代碼爲以下代碼,輸出。
NSMutableString *string = [NSMutableStringstringWithFormat:@"測試文字"];
輸出如下:
2017-08-10 15:41:55.298 text[58856:1225618] 測試文字 String: 0x7d26fb40, 0xbff9c0ac
2017-08-10 15:41:55.298 text[58856:1225618] Strong屬性 String: 0x7d26fb40, 0x7d062af0
2017-08-10 15:41:55.298 text[58856:1225618] Copy 屬性 String: 0x7d274510, 0x7d062af4
結果輸出有不同:此時Copy屬性字符串已不再指向原來String對象,而是深拷貝了String字符串,且copyssString對象指向這個字符串。
在MRC環境下,輸出兩者的引用計數,可以看到String對象的引用計數是2,而copyssString對象的引用計數是1。
如果去修改String字符串的話,可以看到:因爲strongString與原始String是指向同一對象,所以strongString的值也會跟隨着改變(此時strongString的類型實際上是NSMutableString,而不是NSString);而copyssString是指向另一個對象,並不會改變。
4.最後結論
我們知道NSMutableString是NSString的子類,一個NSString指針可以指向NSMutableString對象,strongString指針指向一個可變字符串是正常的。
如上例子可以看出:
1) 當原字符串是NSString時,字符串是不可變的,不管是Strong還是Copy屬性的對象,都是指向原對象,Copy操作只是做了次淺拷貝。
2) 當原字符串是NSMutableString時,Strong屬性只是增加了原字符串的引用計數,而Copy屬性則是對原字符串做了次深拷貝,產生一個新的對象,且Copy屬性對象指向這個新的對象,且這個Copy屬性對象的類型始終是NSString,而不是NSMutableString,因此其是不可變的。
3) 這裏還有一個性能問題,即在原字符串是NSMutableString,Strong是單純的增加對象的引用計數,而Copy操作是執行了一次深拷貝,所以性能上會有所差異(雖然不大)。如果原字符串是NSString時,則沒有這個問題。
所以,在聲明NSString屬性時,到底是選擇strong還是copy,可以根據實際情況來定。不過,一般我們將對象聲明爲NSString時,都不希望它改變,所以大多數情況下,我們建議用copy,以免因可變字符串的修改導致的一些非預期問題。