strong
和copy
修飾NSString
屬性時(shí)的不同
iOS中對(duì)字符串的修飾可以用strong
也可以用copy
,如下所示
@property (nonatomic, copy) NSString *strCopy;
@property (nonatomic, strong) NSString *strStrong;
這個(gè)兩種修飾符的區(qū)別如下
當(dāng)對(duì)這個(gè)屬性賦值一個(gè)不可變的
NSString
對(duì)象時(shí),作用相同洛勉,都是對(duì)字符串對(duì)象地址的淺拷貝舀瓢。由于這個(gè)字符串是個(gè)不可變類型蝇摸,所以恰力,屬性值也不會(huì)變。-
當(dāng)對(duì)這個(gè)屬性賦值一個(gè)可變的
NSMutableString
對(duì)象時(shí)听怕,copy
修飾的屬性是深拷貝,strong
修飾的屬性是淺拷貝废累。當(dāng)原字符串更改,copy的屬性值不會(huì)改變脱盲,而strong修飾的屬性的屬性值會(huì)隨著改變邑滨。- 注意
appendString
才是對(duì)原字符串的改變,stringByAppendingString
等則是返回一個(gè)新的字符串對(duì)象钱反。
- 注意
所以綜合上面的情況掖看,更推薦使用copy
來修飾字符串屬性,提高屬性的安全性面哥。為這個(gè)屬性賦值一個(gè)NSString
對(duì)象兩種效果是相同的哎壳,所以可以用copy,而一旦是賦值一個(gè)NSMutableString
時(shí)候幢竹,copy
的屬性可以保證屬性值不會(huì)隨賦值時(shí)的字符串對(duì)象的變化而變化耳峦,更優(yōu)于strong
修飾。
證明
屬性被賦值不可變字符串
NSString = NSString
@interface ViewController ()
@property (nonatomic, strong) NSString *strStrong;
@property (nonatomic, copy) NSString *strCopy;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSString *text = @"a string object";
self.strStrong = text;
self.strCopy = text;
NSLog(@"原字符串地址 == %p", text);
NSLog(@"strong屬性地址 == %p", self.strStrong);
NSLog(@"copy屬性地址 == %p", self.strCopy);
}
輸出
>>> 原字符串地址 == 0x10c626078
>>> strong屬性地址 == 0x10c626078
>>> copy屬性地址 == 0x10c626078
所以證明焕毫,當(dāng)text
是不可變的NSString
類型時(shí)蹲坷,這種情況下都是同一個(gè)指針地址,指向的是同一個(gè)對(duì)象邑飒。兩種修飾符的效果是一樣的循签。都是淺拷貝。
注意
需要注意的是下面這種情況
- (void)viewDidLoad {
[super viewDidLoad];
NSString *text = @"a string object";
self.strStrong = text;
self.strCopy = text;
text = @"a new string object";
NSLog(@"%@", text);
NSLog(@"%@", self.strStrong);
NSLog(@"%@", self.strCopy);
}
這種情況下的輸出是
>>> a new string object
>>> a string object
>>> a string object
因?yàn)楫?dāng)text = @"a new string object"
的時(shí)候疙咸,text指針指向了新的字符串對(duì)象县匠。而strStrong
和strCopy
屬性的指針仍然是指向了原來的a string object
字符串對(duì)象。他們的指針是不會(huì)跟著變化的
屬性被賦值可變字符串對(duì)象時(shí)
NSString = NSMutableString
- (void) mutableStringTest {
NSMutableString *text = [[NSMutableString alloc] initWithString:@"a mutable string object"];
self.strStrong = text;
self.strCopy = text;
NSLog(@"原字符串地址 == %p", text);
NSLog(@"strong屬性地址 == %p", self.strStrong);
NSLog(@"copy屬性地址 == %p", self.strCopy);
[text appendString:@" after modify"];
NSLog(@"%@", text);
NSLog(@"%@", self.strStrong);
NSLog(@"%@", self.strCopy);
}
輸出
>>> 原字符串地址 == 0x60400025c0b0
>>> strong屬性地址 == 0x60400025c0b0
>>> copy屬性地址 == 0x60400025c3b0
>>> a mutable string object after modify
>>> a mutable string object after modify
>>> a mutable string object
可以看到撒轮,當(dāng)屬性被賦值可變字符串的時(shí)候乞旦,copy
屬性會(huì)拷貝出來一個(gè)新的對(duì)象,而strong
屬性則是對(duì)指針地址的拷貝题山。所以兰粉,當(dāng)原字符串發(fā)送了改變的時(shí)候,copy
屬性的值并不會(huì)發(fā)送變化顶瞳。而strong
屬性的值發(fā)送了變化玖姑。
在這種情況下兩種修飾符的效果是不同的。
為什么copy
修飾的字符串不同類型賦值時(shí)會(huì)產(chǎn)生深淺拷貝
因?yàn)楫?dāng)copy
修飾的屬性慨菱,對(duì)它進(jìn)行賦值的時(shí)候焰络,它的setter
方法中執(zhí)行的是copy
操作。如下所示
- (void)setName:(NSString *)name {
_name = [name copy];
}
因?yàn)槭菆?zhí)行的copy
操作符喝,所以產(chǎn)生了NSString
和NSMutableString
執(zhí)行copy
方法產(chǎn)生的不同結(jié)果闪彼。
當(dāng)NSString
執(zhí)行copy
方法,返回的是仍然是NSString
類型协饲,是做了一次淺拷貝备蚓,只拷貝了字符串對(duì)象的地址
而當(dāng)NSMutableString
執(zhí)行copy
方法课蔬,返回的則是NSString
類型,這做的是一次深拷貝郊尝。
所以,無論是可變類型還是不可變類型字符串战惊,進(jìn)行copy
操作都是復(fù)制出來一個(gè)不可變類型的字符串流昏,區(qū)別在于是否拷貝出來新的對(duì)象。
copy
方法和mutableCopy
方法
既然有copy
方法吞获,同樣還有mutableCopy
方法况凉,這兩個(gè)方法的特點(diǎn)如下
-
拷貝之后的對(duì)象類型的區(qū)別
-
copy
方法拷貝出來的都是不可變類型[NSMutableArray copy] -> NSArray
[NSMutableString copy] -> NSString
[NSString copy] -> NSString
-
mutableCopy
方法拷貝出來的都是可變類型[NSString mutableCopy] -> NSMutableString
[NSArray mutableCopy] -> NSMutableArray
[NSMutableString copy] -> NSMutableString
-
-
是否產(chǎn)生新對(duì)象的區(qū)別
mutableCopy
做的都是深拷貝,得到的都是一個(gè)新的對(duì)象copy
方法只有對(duì)可變類型進(jìn)行操作時(shí)是深拷貝各拷,對(duì)不可變類型進(jìn)行copy是淺拷貝