string屬性用copy和strong修飾符時的不同

strongcopy修飾NSString屬性時的不同

iOS中對字符串的修飾可以用strong也可以用copy,如下所示

@property (nonatomic, copy) NSString *strCopy;
@property (nonatomic, strong) NSString *strStrong;

這個兩種修飾符的區別如下

  • 當對這個屬性賦值一個不可變的NSString對象時,作用相同,都是對字符串對象地址的淺拷貝。由于這個字符串是個不可變類型,所以,屬性值也不會變。

  • 當對這個屬性賦值一個可變的NSMutableString對象時,copy修飾的屬性是深拷貝,strong修飾的屬性是淺拷貝。當原字符串更改,copy的屬性值不會改變,而strong修飾的屬性的屬性值會隨著改變。

    • 注意appendString才是對原字符串的改變,stringByAppendingString等則是返回一個新的字符串對象。

所以綜合上面的情況,更推薦使用copy來修飾字符串屬性,提高屬性的安全性。為這個屬性賦值一個NSString對象兩種效果是相同的,所以可以用copy,而一旦是賦值一個NSMutableString時候,copy的屬性可以保證屬性值不會隨賦值時的字符串對象的變化而變化,更優于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

所以證明,當text是不可變的NSString類型時,這種情況下都是同一個指針地址,指向的是同一個對象。兩種修飾符的效果是一樣的。都是淺拷貝。

注意

需要注意的是下面這種情況

- (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

因為當text = @"a new string object"的時候,text指針指向了新的字符串對象。而strStrongstrCopy屬性的指針仍然是指向了原來的a string object字符串對象。他們的指針是不會跟著變化的


屬性被賦值可變字符串對象時

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

可以看到,當屬性被賦值可變字符串的時候,copy屬性會拷貝出來一個新的對象,而strong屬性則是對指針地址的拷貝。所以,當原字符串發送了改變的時候,copy屬性的值并不會發送變化。而strong屬性的值發送了變化。

在這種情況下兩種修飾符的效果是不同的。


為什么copy修飾的字符串不同類型賦值時會產生深淺拷貝

因為當copy修飾的屬性,對它進行賦值的時候,它的setter方法中執行的是copy操作。如下所示

- (void)setName:(NSString *)name {
    _name = [name copy];
}

因為是執行的copy操作,所以產生了NSStringNSMutableString執行copy方法產生的不同結果。

NSString執行copy方法,返回的是仍然是NSString類型,是做了一次淺拷貝,只拷貝了字符串對象的地址

而當NSMutableString執行copy方法,返回的則是NSString類型,這做的是一次深拷貝。

所以,無論是可變類型還是不可變類型字符串,進行copy操作都是復制出來一個不可變類型的字符串,區別在于是否拷貝出來新的對象。

copy方法和mutableCopy方法

既然有copy方法,同樣還有mutableCopy方法,這兩個方法的特點如下

  • 拷貝之后的對象類型的區別

    • copy方法拷貝出來的都是不可變類型

      [NSMutableArray copy] -> NSArray

      [NSMutableString copy] -> NSString

      [NSString copy] -> NSString

    • mutableCopy方法拷貝出來的都是可變類型

      [NSString mutableCopy] -> NSMutableString

      [NSArray mutableCopy] -> NSMutableArray

      [NSMutableString copy] -> NSMutableString

  • 是否產生新對象的區別

    • mutableCopy做的都是深拷貝,得到的都是一個新的對象

    • copy方法只有對可變類型進行操作時是深拷貝,對不可變類型進行copy是淺拷貝

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 清官的生活在哪里? 在寒宅里 在清苦的生活里 在對家人的刻薄里 在同僚們排斥的孤獨里 在人情世故的小心里 在不解人...
    武陵清泉閱讀 186評論 0 3
  • 接觸到思維導圖是在2015年的時候,并跟隨童老師正式學習過,也算是入門吧!當時,學完后的感覺是思維變寬,整個人也很...
    心陽青青閱讀 435評論 3 4
  • 浮生著甚苦奔忙?盛席華筵終散場。 悲喜千般同幻渺,古今一夢盡荒唐。 列位:上一回正說到倉鼠...
    梨花一枝閱讀 229評論 0 1
  • 每天中午吃飯,美妞都幫我專門拿個盤子幫我配好餐,每樣食物按照碳水化合物、脂肪、蛋白質等均衡搭配好,說是給我的健身餐...
    E姐小酒窩閱讀 182評論 0 0