作為一個有好幾年的開發(fā)人員來說,有時候我們知道怎么用,但是不知道為什么要這么用,也就是知其然,不知其所以然,對于以前的我來說我是一個不求甚解的人。但是作為一個專業(yè)的技術人,要想更上一層樓。還是要知其所以然的為好,特別是技術面試,就能決定一個人的內(nèi)力到底有多深了。
實戰(zhàn)
首先我們創(chuàng)建兩個屬性,一個copy修飾, 一個strong修飾
@interface ViewController ()
@property(nonatomic, strong) NSString *strongStr;
@property(nonatomic, copy) NSString *copyedStr;
@end
第一種情況
- (void)testOne {
NSString *str = [NSString stringWithFormat:@"ikonan"];
self.strongStr = str;
self.copyedStr = str;
// %p str 內(nèi)容內(nèi)存首地址
// %p &str 變量str內(nèi)存的首地址
NSLog(@"originString: %p, %p, %@",str, &str, str);
NSLog(@"strongString: %p, %p, %@",_strongStr, &_strongStr, self.strongStr);
NSLog(@"copyedString: %p, %p, %@",_copyedStr, &_copyedStr, self.copyedStr);
str = @"abc";
NSLog(@"originString: %p, %p, %@",str, &str, str);
NSLog(@"strongString: %p, %p, %@",_strongStr, &_strongStr, self.strongStr);
NSLog(@"copyedString: %p, %p, %@",_copyedStr, &_copyedStr, self.copyedStr);
//運行結果
originString: 0xa006e616e6f6b696, 0x16b1a53a8, ikonan
strongString: 0xa006e616e6f6b696, 0x10520d190, ikonan
copyedString: 0xa006e616e6f6b696, 0x10520d198, ikonan
originString: 0x104c600f0, 0x16b1a53a8, abc
strongString: 0xa006e616e6f6b696, 0x10520d190, ikonan
copyedString: 0xa006e616e6f6b696, 0x10520d198, ikonan
}
結論
當string為不可變字符串時(這種情況strong 和 copy沒區(qū)別)
不管是strong還是copy屬性的對象,其指向的地址都是同一個,即為string指向的地址。
當string的值發(fā)生改變時,兩個對象的值也保持原來的值
第二種情況
- (void)testTwo {
NSMutableString *str = [[NSMutableString alloc] initWithString:@"ikonan"];
self.strongStr = str;
self.copyedStr = str;
NSLog(@"originString: %p, %p, %@",str, &str, str);
NSLog(@"strongString: %p, %p, %@",_strongStr, &_strongStr, self.strongStr);
NSLog(@"copyedString: %p, %p, %@",_copyedStr, &_copyedStr, self.copyedStr);
[str appendString:@"123"];
NSLog(@"originString: %p, %p, %@",str, &str, str);
NSLog(@"strongString: %p, %p, %@",_strongStr, &_strongStr, self.strongStr);
NSLog(@"copyedString: %p, %p, %@",_copyedStr, &_copyedStr, self.copyedStr);
}
//運行結果
originString: 0x1c0252570, 0x16b7f53a8, ikonan
strongString: 0x1c0252570, 0x14bd07ba0, ikonan
copyedString: 0xa006e616e6f6b696, 0x14bd07ba8, ikonan
originString: 0x1c0252570, 0x16b7f53a8, ikonan123
strongString: 0x1c0252570, 0x14bd07ba0, ikonan123
copyedString: 0xa006e616e6f6b696, 0x14bd07ba8, ikonan
結論
當string為可變字符串時(copy 深拷貝, strong 就是淺拷貝)
- 此時copy屬性字符串已不再指向string字符串對象,而是深拷貝了string字符串,并讓_copyedStr對象指向這個字符串
- _strongStr與string是指向同一對象,所以_strongString的值也會跟隨著改變(需要注意的是,此時_strongStr的類型實際上是NSMutableString,而不是NSString);而_copyedStr是指向另一個對象的,所以并不會改變。
總結
在聲明NSString屬性時,到底是選擇strong還是copy,可以根據(jù)實際情況來定。不過,一般我們將對象聲明為NSString時,都不希望它改變,所以大多數(shù)情況下,我們建議用copy,以免因可變字符串的修改導致的一些非預期問題。