iOS开发关于深拷贝、浅拷贝和可变拷贝

释放双眼,带上耳机,听听看~!

经常在论坛和群里看到有人问拷贝相关的问题,回答的总是五花八门、千奇百怪。如果你对几种拷贝的概念还不是很清晰,这篇文章会有帮助。

什么是浅拷贝

在谈论深拷贝、浅拷贝等概念之前,先要清楚什么叫拷贝。拷贝(copy)就是复制。当我们已经有一个对象例如:

NSString *str = @"abc";

那么我想有一个str2和str的值一样该怎么做呢?最简单的办法就是这样:

NSString *str2 = str;

实际上,这就是浅拷贝,str和str2的内存地址是一样的。也就是说两个指针指向了同一块内存,因此实际上并没有东西被复制出来,就好比文件的快捷方式,无论一个文件有多少快捷方式,这个文件始终只有一个。那么如果我不想要快捷方式,就想要两个文件呢?

NSString *str3 = [str copy];

理论上来说,这样会划分新的内存地址,生成新的对象,但是实际打印会发现str和str3的地址是一样的。这是因为OC对NSString做了内存管理的优化,这种值相同的string会直接浅拷贝。这也说明,正常情况下NSString是不需要深拷贝的。

什么是深拷贝

那么什么时候需要深拷贝呢?其实深拷贝在开发中经常用到:

@property (nonatomic, copy) NSString *name;

类似这样的属性项目中肯定多的数不清(当然如果你写成@property (nonatomic, strong) NSString *name;是不对的,你的项目会有可能出现莫名其妙的bug)。见名知意,声明为copy的属性在被赋值的时候实际上是会执行copy方法的,就像这样:

- (void)setName:(NSString *)name{
_name = [name copy];
}

为什么要这么做呢?假如我们就将name声明为strong。NSString有个子类NSMutableString,我们是可以将NSMutableString对象赋值给NSString的,像这样:

NSMutableString *mutableName = [NSMutableString stringWithString:@"Mike"];
self.name = mutableName;

然而如果我们在后面的代码中修改了mutableName的值,name的值也会随之改变。这当然是不合理的,NSString的值应该是不变的。而copy的作用就是这个。通过copy方法,创建了一个新的值和mutableName相同的对象,所以mutableName的值改变并不会影响到name。

什么是可变拷贝mutableCopy

同样见名知意,就是拷贝出一个可变的对象出来。例如:

NSMutableString *mutableStr = [@"abc" mutableCopy];

通过对NSString进行mutableCopy而产生了一个NSMutableString。我见过一些人创建mutableString就是这样写的,但是从代码规范和效率的角度讲,这样做是不推荐的。

copy的妙用

copy方法除了可以对对象进行深拷贝以外还有个优点就是,相比于重新创建一个对象,copy的效率更高。例如要创建一百个MyClass对象,实例化一个对象然后使用copy方法的效率要比实例化一百次高得多。

人已赞赏
iOS文章

iOS开发应用之间的跳转

2020-1-28 11:52:53

iOS文章

iOS开发解决IQKeyboardManager失效的问题

2020-1-28 14:29:08

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索