【面试题】为什么字符串用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等同理.

posted @ 2017-10-24 17:50  王彬iOS  阅读(1713)  评论(0编辑  收藏  举报