面试中我们经常会问到copy!为什么选择使用copy?
原因是NSString属性可能被传入一个NSString实例,也可能是一个NSMutableString实例。当传入了一个NSMutableString实例时,字符串的值可能会在背后悄悄变化。
如下例子:
@interface Book : NSObject
@property (strong, nonatomic) NSString *title;
@end
在另一个类中,我们有一个这样的方法:
- (void)stringExample {
NSMutableString *bookTitle = [NSMutableString stringWithString:@"English book"];
Book *book = [[Book alloc] init];
book.title = bookTitle;
[bookTitle setString:@"Chinese book"];
NSLog(@"book title %@", book.title);
}
运行后会发现,book.title是“Chinese book”。如果我们更改为使用copy声明title属性,book.title变成“English book”。
当使用strong时,字符串的retain计数将增加1,属性与字符串指向同一个内存地址。这意味着任何指向这个内存地址的变量都可改变这个值,执行[bookTitle setString:@"Chinese book"]后bookTitle变量的值改变后,title属性值也跟随变化。
如果改用copy,则会为Book类创建一个字符串副本,也就是说修改booTitle,不再会影响字符串副本值,这是多数情况下我们想要的结果。所以开发中对于NSString类型大多情况下都使用copy。
浅拷贝是指针拷贝,还是指向用一个内存空间,只要任何操作修改了指针指向的那块内存空间,就可以改变内存空间的值,而深拷贝,是拷贝一份新的内容,生成搞一个新的对象,包括生成一份新的内存空间,修改新的对象自然不会影响到旧的对象。
对于深浅拷贝没那么复杂,只要记住一点,是否会生成新的对象!
- 如下分析:
可变的对象 -> copy/mutablecopy -> 生成一个可变的新对象, 是深拷贝
不可变的对象 -> mutablecopy -> 生成一个可变的的新对象,是深拷贝
不可变的对象 -> copy -> 生成一个不可变的, 俩个都是不可变的, 系统进行内存优化, 应该属于同一个内存空间, 不会生成新对象, 是浅拷贝 - 另外:
如果是浅拷贝:不会生成新的对象,但是系统就会对原来的对象进行retain,所以需要对原来的对象进行一次release
如果是深拷贝:会生成新的对象,系统不会对原来的对象进行retain,但是因为生成了新的对象,所以我们需要对新的对象进行release