一言以蔽之:爲了安全!安全
當一個可變字符串(NSMutableString)賦值給一個字符串屬性(不管這個字符串是NSString仍是NSMutableString),atom
若是此屬性是retain修飾的,就是淺拷貝,引用計數加1。賦值後源字符串改變,這個屬性值也跟着改變。spa
若是此屬性是copy修飾的,就是深拷貝,引用計數等於1(由於從堆裏新分配一個內存塊)。賦值後源字符串改變,這個屬性值不會改變。(保證了安全)code
假設對象有下面4個屬性:對象
1 @property (retain, nonatomic) NSString *retainStr; 2 @property (copy, nonatomic) NSString *copyStr; 3 @property (retain, nonatomic) NSMutableString *retainMStr; 4 @property (copy, nonatomic) NSMutableString *copyMStr;
1 NSMutableString *mStr = [NSMutableString string]; 2 3 [mStr setString:@"我沒變-------"]; 4 self.retainStr = mStr; // 淺拷貝,引用計數加1, 5 NSLog(@"%ld",[self.retainStr retainCount]);// 2 6 7 self.copyStr = mStr; // 深拷貝, 8 NSLog(@"%ld",[self.copyStr retainCount]);// 1 9 10 self.retainMStr = mStr; // 淺拷貝,引用計數加1, 11 NSLog(@"%ld",[self.retainMStr retainCount]);// 3 12 13 self.copyMStr = mStr; // 深拷貝 14 NSLog(@"%ld",[self.copyMStr retainCount]);// 1 15 16 17 18 NSLog(@"retainStr:%@", self.retainStr); 19 NSLog(@"copyStr:%@", self.copyStr); 20 NSLog(@"retainMStr:%@", self.retainMStr); 21 NSLog(@"copyMStr:%@", self.copyMStr); 22 23 NSLog(@"\n"); 24 25 [mStr setString:@"我變了--------"]; 26 27 NSLog(@"retainStr:%@", self.retainStr);// 淺拷貝 28 NSLog(@"%ld",[self.retainStr retainCount]);// 3 29 30 NSLog(@"copyStr:%@", self.copyStr);// 深拷貝 31 NSLog(@"%ld",[self.copyStr retainCount]);// 1 32 33 NSLog(@"retainMStr:%@", self.retainMStr);// 淺拷貝 34 NSLog(@"%ld",[self.retainMStr retainCount]);// 3 35 36 NSLog(@"copyMStr:%@", self.copyMStr);// 深拷貝 37 NSLog(@"%ld",[self.copyMStr retainCount]);// 1 38 39 NSLog(@"\n");
當一個不可變字符串(NSString)賦值給一個字符串屬性(不管這個字符串是NSString仍是NSMutableString),就不存在安全性問題,都是深拷貝。此時不管retain仍是copy都無所謂。blog
1 NSString *str = @"我來了";//[[NSString alloc] initWithString:@"我來了"];//兩種方式都同樣。都在常量區 2 3 self.retainStr = str; 4 self.copyStr = str; 5 self.retainMStr = [str mutableCopy]; 6 self.copyMStr = [str mutableCopy]; 7 8 NSLog(@"retainStr:%@", self.retainStr); 9 NSLog(@"copyStr:%@", self.copyStr); 10 NSLog(@"retainMStr:%@", self.retainMStr); 11 NSLog(@"copyMStr:%@", self.copyMStr); 12 13 NSLog(@"\n"); 14 15 str =@"我走了";//[[NSStringalloc] initWithString:@"我走了"];//兩種方式都同樣 16 17 NSLog(@"retainStr:%@", self.retainStr); 18 NSLog(@"copyStr:%@", self.copyStr); 19 NSLog(@"retainMStr:%@", self.retainMStr); 20 NSLog(@"copyMStr:%@", self.copyMStr); 21 22 NSLog(@"\n");
打印結果以下:內存
1 2016-06-16 12:24:36.818 OCLession9[5278:90728] retainStr:我來了 2 2016-06-16 12:24:36.819 OCLession9[5278:90728] copyStr:我來了 3 2016-06-16 12:24:36.819 OCLession9[5278:90728] retainMStr:我來了 4 2016-06-16 12:24:36.819 OCLession9[5278:90728] copyMStr:我來了 5 2016-06-16 12:24:36.819 OCLession9[5278:90728] 6 2016-06-16 12:24:36.819 OCLession9[5278:90728] retainStr:我來了 7 2016-06-16 12:24:36.819 OCLession9[5278:90728] copyStr:我來了 8 2016-06-16 12:24:36.819 OCLession9[5278:90728] retainMStr:我來了 9 2016-06-16 12:24:36.819 OCLession9[5278:90728] copyMStr:我來了