天天看點

NSString屬性聲明中的copy和retain差別 NSString屬性聲明中的copy和retain差別

NSString屬性聲明中的copy和retain差別

前幾天去面試,被問到了NSString屬性聲明中的copy和retain具體差別,對記憶體計數的影響,汗,當時沒整明白,也沒答出來,隻知道NSString一般用copy.

首先做以下幾個變量聲明:

@property (retain, nonatomic) NSString *retainStr;

@property (copy, nonatomic)   NSString *copyStr;

@property (retain, nonatomic) NSMutableString *retainMStr;

@property (copy, nonatomic)   NSMutableString *copyMStr;

實作代碼如下:

    NSMutableString *mStr = [NSMutableString string];

    [mStr setString:@"我沒變"];

    self.retainStr   = mStr;

    self.copyStr     = mStr;

    self.retainMStr = mStr;

    self.copyMStr   = mStr;

    NSLog(@"retainStr:%@",  self.retainStr);

    NSLog(@"copyStr:%@",    self.copyStr);

    NSLog(@"retainMStr:%@", self.retainMStr);

    NSLog(@"copyMStr:%@",   self.copyMStr);

    NSLog(@"\n");

    [mStr setString:@"我變了"];

    NSLog(@"retainStr:%@",  self.retainStr);

    NSLog(@"copyStr:%@",    self.copyStr);

    NSLog(@"retainMStr:%@", self.retainMStr);

    NSLog(@"copyMStr:%@",   self.copyMStr);

    NSLog(@"\n");

    NSString *str = @"我來了";//[[NSString alloc] initWithFormat:@"我來了"];//兩種方式都一樣。

    self.retainStr  = str;

    self.copyStr    = str;

    self.retainMStr = [str mutableCopy];

    self.copyMStr   = [str mutableCopy];

    NSLog(@"retainStr:%@",  self.retainStr);

    NSLog(@"copyStr:%@",    self.copyStr);

    NSLog(@"retainMStr:%@", self.retainMStr);

    NSLog(@"copyMStr:%@",   self.copyMStr);

    NSLog(@"\n");

    str =@"我走了";//[[NSStringalloc] initWithFormat:@"我走了"];//兩種方式都一樣

    NSLog(@"retainStr:%@",  self.retainStr);

    NSLog(@"copyStr:%@",    self.copyStr);

    NSLog(@"retainMStr:%@", self.retainMStr);

    NSLog(@"copyMStr:%@",   self.copyMStr);

    NSLog(@"\n");

列印結果如下:

2012-10-12 13:53:14.858 StringDemo[1515:11303] retainStr:我沒變

2012-10-12 13:53:14.860 StringDemo[1515:11303] copyStr:我沒變

2012-10-12 13:53:14.861 StringDemo[1515:11303] retainMStr:我沒變

2012-10-12 13:53:14.862 StringDemo[1515:11303] copyMStr:我沒變

2012-10-12 13:53:14.863 StringDemo[1515:11303] 

2012-10-12 13:53:14.864 StringDemo[1515:11303] retainStr:我變了

2012-10-12 13:53:14.865 StringDemo[1515:11303] copyStr:我沒變

2012-10-12 13:53:14.866 StringDemo[1515:11303] retainMStr:我變了

2012-10-12 13:53:14.867 StringDemo[1515:11303] copyMStr:我沒變

2012-10-12 13:53:14.868 StringDemo[1515:11303] 

2012-10-12 13:53:14.869 StringDemo[1515:11303] retainStr:我來了

2012-10-12 13:53:14.869 StringDemo[1515:11303] copyStr:我來了

2012-10-12 13:53:14.870 StringDemo[1515:11303] retainMStr:我來了

2012-10-12 13:53:14.871 StringDemo[1515:11303] copyMStr:我來了

2012-10-12 13:53:14.872 StringDemo[1515:11303] 

2012-10-12 13:53:14.873 StringDemo[1515:11303] retainStr:我來了

2012-10-12 13:53:14.874 StringDemo[1515:11303] copyStr:我來了

2012-10-12 13:53:14.875 StringDemo[1515:11303] retainMStr:我來了

2012-10-12 13:53:14.876 StringDemo[1515:11303] copyMStr:我來了

由此可以看出:對源頭是NSMutableString的字元串,retain僅僅是指針引用,增加了引用計數器,這樣源頭改變的時候,用這種retain方式聲明的變量(無論被指派的變量是可變的還是不可變的),它也會跟着改變;而copy聲明的變量,它不會跟着源頭改變,它實際上是深拷貝。對源頭是NSString的字元串,無論是retain聲明的變量還是copy聲明的變量,當第二次源頭的字元串重新指向其它的地方的時候,它還是指向原來的最初的那個位置,也就是說其實二者都是指針引用,也就是淺拷貝。

另外說明一下,這兩者對記憶體計數的影響都是一樣的,都會增加記憶體引用計數,都需要在最後的時候做處理。

其實說白了,對字元串為啥要用這兩種方式?我覺得還是一個安全問題,比如聲明的一個NSString *str變量,然後把一個NSMutableString *mStr變量的指派給它了,如果要求str跟着mStr變化,那麼就用retain;如果str不能跟着mStr一起變化,那就用copy。而對于要把NSString類型的字元串指派給str,那兩都沒啥差別。不會影響安全性,記憶體管理也一樣。