(0087)iOS开发之NSString属性为什么要用copy来修饰?

2025-06-06 00:03:01 2014德国世界杯

这个问题既是一个面试题,也是开发中经常遇到的问题,NSString 属性到底用copy 还是 strong ?其实如果明白的两者的区别也就不会疑惑了,其实都可以,只是如果你不明白两者的实质的区别,有可能会出现难以发现的异常。但是我们遇到的又很少所有经常用哪个都行,但是不知道有何区别,在此我实际验证一下。记录这个经常模糊不清的问题。

1.快速搭建一个demo

- (void)viewDidLoad {

[super viewDidLoad];

// Do any additional setup after loading the view, typically from a nib.

NSLog(@"\n");

// 验证不可变对象NSString

[self test];

// 验证可变对象NSMutableString

// [self test22];

// 如果用NSString赋值的话strong和copy(此刻是浅拷贝)是没有区别的

// 如果用NSMutableString赋值的话strong没有只是增加了str1的计数器,并没有开辟新的内存

// copy的话开辟了新的内存,对string的内容进行修改的话,strong的字符串内容改变了,而copy的并没有改变

// 如果需要改变的话可以用strong,如果不需要改变的话用copy

// 所以属性指向可变对象时应注意;

}

- (void)test{

NSString *string = [NSString stringWithFormat:@"测试文字"];//注释1

self.strongStr = string;

self.copyssStr = string;

NSLog(@"String:%@ strongStr:%@ copyssStr:%@",string,self.strongStr,self.copyssStr);

NSLog(@"String : %p, %p", string, &string);

NSLog(@"Strong属性: %p, %p",_strongStr, &_strongStr);

NSLog(@"Copy 属性: %p, %p",_copyssStr, &_copyssStr);

NSLog(@"\n");

string = @"我变了,你没变";

NSLog(@"我变 String:%@ strongStr:%@ copyssStr:%@",string,self.strongStr,self.copyssStr);

NSLog(@"我变 String : %p, %p", string, &string);

NSLog(@"我变 Strong属性: %p, %p",_strongStr, &_strongStr);

NSLog(@"我变 Copy 属性: %p, %p",_copyssStr, &_copyssStr);

// NSString总结:用NSString赋值的话strong和copy(此刻是浅拷贝)是没有区别的;从新赋值,相当于指向了新的一个对象,string指向变了,而strong和copy指针(此刻是浅拷贝

// 还是指向的原来的对象,所以说不变。

// 所以不可变对象的copy 和strong 与可变对象的copy 一样效果,赋值后copy 和 strong 指针指向的值都不变;

/*

1. 当原字符串是NSMutableString时,Strong属性只是增加了原字符串的引用计数,而Copy属性则是对原字符串做了次深拷贝,产生一个新的对象,且Copy属性对象指向这个新的对象,且这个Copy属性对象的类型始终是NSString,而不是NSMutableString,因此其是不可变的。

2. 这里还有一个性能问题,即在原字符串是NSMutableString,Strong是单纯的增加对象的引用计数,而Copy操作是执行了一次深拷贝,所以性能上会有所差异(虽然不大)。如果原字符串是NSString时,则没有这个问题。

所以,在声明NSString属性时,到底是选择strong还是copy,可以根据实际情况来定。不过,一般我们将对象声明为NSString时,都不希望它改变,所以大多数情况下,我们建议用copy,以免因可变字符串的修改导致的一些非预期问题。

*/

}

- (void)test22{

//

NSMutableString *string = [NSMutableString stringWithFormat:@"测试文字"];

self.strongStr = string;

self.copyssStr = string;

NSLog(@"String:%@ strongStr:%@ copyssStr:%@",string,self.strongStr,self.copyssStr);

NSLog(@"String 地址: %p, %p", string, &string);

NSLog(@"Strong 地址: %p, %p",_strongStr, &_strongStr);

NSLog(@"Copy 地址: %p, %p",_copyssStr, &_copyssStr);

NSLog(@"\n");

[string appendString:@"我变了,你没变"];

NSLog(@"append 后 String:%@ strongStr:%@ copyssStr:%@",string,self.strongStr,self.copyssStr);

NSLog(@"append 后 String 地址: %p, %p", string, &string);

NSLog(@"append 后 Strong 地址: %p, %p",_strongStr, &_strongStr);

NSLog(@"append 后 Copy 地址: %p, %p",_copyssStr, &_copyssStr);

NSLog(@"\n");

// NSMutableString总结:

// 如果string 的指针不变,内存地址不变,值变化,则strongStr 的值跟着变化,指针不变,地址不变;而copyssStr 则不会任何变化;

string = [NSMutableString stringWithFormat:@"ccvcc"];

NSLog(@"Mutable 后 String:%@ strongStr:%@ copyssStr:%@",string,self.strongStr,self.copyssStr);

NSLog(@"Mutable 后 String 地址: %p, %p", string, &string);

NSLog(@"Mutable 后 Strong 地址: %p, %p",_strongStr, &_strongStr);

NSLog(@"Mutable 后 Copy 地址: %p, %p",_copyssStr, &_copyssStr);

// 总结:Mutable 相当于重新alloc一个对象, string 指针的指向变了,指向了新的对象的地址,strongStr 指针不变,指向的还是原来对象的地址,地址不变;而copyssStr已经去string没有关系,则不会任何变化;

// 这里我想验证下strongStr 指向的是原来的还是新的对象的

[self performSelector:@selector(shows) withObject:nil afterDelay:10];

}

- (void)shows {

NSLog(@"shows 后 strongStr:%@ copyssStr:%@",self.strongStr,self.copyssStr);

}

上面代码中有自己对比得出的结论,推出多用copy 是因为我们使用属性一般是全局的,不期望 *string被改变时,也改变了copy 属性的值。我们希望的是self.copyssStr = @"";来改变

参考:https://www.jianshu.com/p/8bbe01e53114

:https://blog.csdn.net/itianyi/article/details/9018567

:https://blog.csdn.net/summer_csdn123/article/details/52190879

:https://www.jianshu.com/p/b3873ac9259b

最新发表
友情链接