首先来介绍一下对象的拷贝的概念吧:
为什么要由对象的拷贝这么一个概念呢?看一个场景:假如现在一个对象中又一个数组对象,现在我们生成一个对象,同时将这个对象赋值给另外一个对象,那么现在问题是这两个对象中的数组对象是同一个,那么如果一个对象中去修改这个数值中的内容,另外一个对象中的数组内容也会被修改,相当于这个数组对象是共享的,当然我们有时候是不希望这种形式的出现的,这时候我们就出现了对象的拷贝。
具体来看一个例子吧
一、系统类对象的拷贝
-
-
-
-
-
-
-
-
- #import <Foundation/Foundation.h>
-
-
-
-
- int main(int argc, const charchar * argv[]) {
- @autoreleasepool {
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- NSMutableArray *array1 = [NSMutableArray arrayWithObjects:@"one",@"two",nil];
-
-
-
- NSMutableArray *array2 = [array1 copy];
-
-
-
- NSMutableArray *array3 = [array1 mutableCopy];
-
- if(array1 != array2){
- NSLog(@"array1 != array2");
- NSLog(@"array1的引用计数:%ld",array1.retainCount);
- NSLog(@"array2的引用计数:%ld",array2.retainCount);
- }
- [array2 release];
- [array1 release];
-
-
- }
- return 0;
- }
我们看到,NSMutableArray有一个mutableCopy方法,这样返回的一个数组对象就是一个拷贝对象了。
但是这里需要注意的是:
copy方法和mutableCopy方法的区别
这两个方法的区别只在于那些有可变对象和不可变对象之分的对象上,对于没有这种区分的对象来说,这两个方法的效果是一样的。
[不可变对象 copy]是假拷贝,等价于[不可变对象 retain]
[不可变对象 mutableCopy是真拷贝
二、深拷贝和浅拷贝
在拷贝对象中也是有深拷贝和浅拷贝之分的
浅拷贝:只拷贝所有属性对象的指针
深拷贝:拷贝属性对象的内容
看个例子:
Person.h
-
-
-
-
-
-
-
-
- #import <Foundation/Foundation.h>
-
- @interface Person : NSObject <NSCopying>
-
- @property(nonatomic,retain)NSMutableArray *apples;
- @property(nonatomic)int age;
-
- @end
Person.m
-
-
-
-
-
-
-
-
- #import "Person.h"
-
- @implementation Person
-
- - (id)copyWithZone:(NSZone *)zone{
-
-
-
- Person * p = [[self class] allocWithZone:zone];
-
-
-
- p.apples = [_apples mutableCopy];
- p.age = _age;
-
- [p.apples release];
-
-
-
-
-
- return p;
- }
-
- @end
我们看到,Person实现了NSCopying协议,然后需要实现一个方法:copyWithZone
在这个方法中我们开始进行拷贝操作:
Person类中有一个属性类型是数组
这里我们需要生成一个Person对象,然后进行属性的拷贝,最后在返回这个对象
浅拷贝:直接复制数组指针
深拷贝:直接复制数组的内容,这里可以直接使用mutableCopy方法进行实现
测试类
main.m
-
-
-
-
-
-
-
-
- #import <Foundation/Foundation.h>
- #import "Person.h"
-
-
-
- int main(int argc, const charchar * argv[]) {
- @autoreleasepool {
-
- NSMutableArray *array1 = [NSMutableArray arrayWithCapacity:2];
-
- for(int i=0;i<2;i++){
- Person *p = [[Person alloc] init];
- [array1 addObject:p];
- [p release];
- }
-
-
- for(Person *p in array1){
- NSLog(@"复制之前的引用计数:%ld",p.retainCount);
- NSLog(@"复制之前的指针:%p",p);
- }
-
-
-
-
- NSArray *array2 = [array1 copy];
- for(Person *p in array2){
- NSLog(@"复制之前的引用计数:%ld",p.retainCount);
- NSLog(@"复制之前的指针:%p",p);
- }
-
-
-
- Person *p = [[Person alloc] init];
- p.apples = [NSMutableArray arrayWithObjects:@"iphone",@"ipad", nil nil];
- p.age = 20;
-
- Person *p1 = [p copy];
-
- if(p != p1){
- NSLog(@"p1.age=%d",p1.age);
- NSLog(@"p1.apples=%@",p1.apples);
- }
-
- }
- return 0;
- }
三、字符串的拷贝
-
-
-
-
-
-
-
-
- #import <Foundation/Foundation.h>
-
- #import "Person.h"
-
-
- int main(int argc, const charchar * argv[]) {
- @autoreleasepool {
- Person *p = [[Person alloc] init];
- NSMutableString *name = [NSMutableString stringWithString:@"jack"];
- p.name = name;
-
-
-
-
-
-
- [name appendString:@"-tom"];
-
-
-
-
-
-
-
-
-
-
- }
- return 0;
- }
这里为什么要单独说一下字符串的拷贝呢?
因为字符串是一个特殊的对象,我们应该调用他的copy方法。因为我们对于字符串其实我们是期望他只有一分值得,就看上面的例子:
我们用NSMutableString产生一个name,然后将其赋值给person对象,当我们在外面修改name的内容的时候,其实person的name属性的值也应该修改。所以我们一般在拷贝字符串对象的时候,都会调用他的copy方法
总结
这一篇文章主要介绍了OC中对象拷贝的相关概念和知识点。我们在操作对象的时候,有时候进行拷贝,还要仔细考虑一下是深拷贝还是浅拷贝。