【面试题】为什么字符串用copy修饰
1.
假如有一个NSMutableString,现在用他给一个retain修饰 NSString赋值,那么只是将NSString指向了NSMutableString所指向的位置,并对NSMUtbaleString计数器加一,此时,如果对NSMutableString进行修改,也会导致NSString的值修改,原则上这是不允许的. 如果是copy修饰的NSString对象,在用NSMutableString给他赋值时,会进行深拷贝,及把内容也给拷贝了一份,两者指向不同的位置,即使改变了NSMutableString的值,NSString的值也不会改变.
所以用copy是为了安全,防止NSMutableString赋值给NSString时,前者修改引起后者值变化而用的.
2
我这样说你就明白了 A->B A中的一个MutableString给B中的一个Property(NSString类型)赋值 首先是能接受的,父类可以接受子类,如果是retain,仅仅是生成一个指针,计数器加一,然后指向那个MutableString。如果MString改变,B中那个跟着改变,因为是同一块内存区域。而选择Copy相当于又生成了一个NSString,与A中的MutableString独立。
3.
下面我想通过一个最简单的例子来说明它们的区别:
首先我们来看看使用strong会出现什么样的情况:
.h
@property (nonatomic, strong) NSString *name;
.m
NSMutableString *mStr = [NSMutableString stringWithString:@"张三"];
self.name = mStr;
NSLog(@"使用strong第一次得到的名字:%@", self.name);
[mStr appendString:@"丰"];
NSLog(@"使用strong第二次得到的名字:%@", self.name);
打印结果:
2017-04-07 16:20:10.138793 copyTest[2421:682898]使用strong第一次得到的名字:张三
2017-04-07 16:20:10.138884 copyTest[2421:682898]使用strong第二次得到的名字:张三丰
结论:
通过上面的例子我们可以看出,我们在没有直接修改 self.name 的情况下 self.name 却被修改了,就好像一个人的名字怎么能没有经过自己同意就被修改呢?我们的初衷只是想修改mStr,但是 self.name 却被意外的修改了,而这就是我们使用strong所不想看到的,它会破坏程序的封装性。(使用strong后 self.name 和 mStr 指向的是同一片内存,所以修改其中一个值后两个值就都变了)
那么使用copy又会得到什么结果呢?下面是使用copy的例子:
.h
@property (nonatomic, copy) NSString *name;
.m
NSMutableString *mStr = [NSMutableString stringWithString:@"张三"];
self.name = mStr;
NSLog(@"使用copy第一次得到的名字:%@", self.name);
[mStr appendString:@"丰"];
NSLog(@"使用copy第二次得到的名字:%@", self.name);
打印结果:
2017-04-07 16:35:04.012589 copyTest[2428:685221]使用copy第一次得到的名字:张三
2017-04-07 16:35:04.012676 copyTest[2428:685221]使用copy第二次得到的名字:张三
结论:
这个例子中我们使用了copy修饰,mStr通过copy得到了一个新的对象赋值给 self.name 这样我们再修改mStr就跟 self.name 没关系了,只有直接对 self.name 进行赋值才能改变它的值,这样就保证了程序的封装性。
为什么使用copy而不是strong以上只是一个例子,还有很多情况可以自己去试试,并且可以把属性类型改成NSMutableString进行不同情况的研究,也可以更加深入理解深拷贝和浅拷贝的含义。
4.
copy会重新生成一个string,被copy的对象发生改变时,copy后的对象不改变
strong仅仅进行强引用确保持有string的对象在生存期间这个string不会被释放
题主说的问题有点问题,应该是NSString用copy或strong都可以,下面分场景说:
- 必须使用copy的场景:A对象持有string记做A.string,然后赋值给B对象,记做B.string,若希望B.string的内容改变时A.string不改变就必须用copy
- 必须用strong的场景:若希望B.string的内容改变时同时A.string也改变则必须用strong
- 随便用哪个的场景:string的内容不会被改变的情况下
以上规则不止适用于NSString,NSArray,NSDictionary等同理.