iOS中的复制对象 浅,深复制

来源:互联网 发布:java实例化对象的方法 编辑:程序博客网 时间:2024/05/16 18:11

对象复制,顾名思义就是将一个已有的对象复制一份出来,开辟一个新的内存来储存对象,相当于一个副本;对象复制又分为浅拷贝和深拷贝;这里我们就来简单的介绍下对象复制。

Foundation框架张支持复制的对象有NString、NSArra、NSNumber、NSDictionar、NSMutableString、NSMutablerArray、NSMutableDictionary等。我们可以自定义对象来支持复制,一个前提条件就会必须实现NSCopying协议或者NSMutableCopying协议或者两者都实现。

 

首先我们先来区分下copy、retain,先举个例子,可能会更清晰很多;

NSArray *array = @[@"one", @"two", @"three", @"four" ];

NSMutableArray *array1 = [array retain];

[array1 removeLastObject];

for(NSObject* obj in array)

{

     NSLog(@"%@", obj);

}

 

NSArry *array2 = @[@"one", @"two", @"three", @"four" ];

NSMutableArray *array3 = [array copy];

[array3 removeLastObject];

for(NSObject* obj in array2)

{

     NSLog(@"%@", obj);

}

 

这样打印出来的结果是,第一次打印的时候只打印出3个元素,第二次打印的时候打印出4个元素。

retain、copy总结:

retain只是引用计数加1,两个指针指同一个内存,也就是array和array1共享一块内存;

copy是开辟出一个内存,两个指针指向两块内存,array2、array3都拥有自己的内存;

 

复制对象的种类:

copy:产生对象的副本是不可变的

mutableCopy:产生的对象副本是可变的

可变与不可变的区别就是是否可以对对象内容进行增删改,比如NSMutableArray与NSArray,我们可以为NSMutableArray增加元素、删除元素、修改元素等操作,而对于NSArray对象就不可以。

同样我们举个例子来区分下copy与mutablecopy:

 

NSArray *array = [[NSArray alloc] initWithObject:@"one", @"two", @"three",nil];

NSArray *array1 = [array copy];

NSMutableArray * array2 = [array muttablecopy];

[array1 addObject:@"five"]; //程序执行到这里报错

[array2 addObject:@"four"];

 

很明显,copy和mutablecopy返回的对象不同,copy返回的是不可变的,mutablecopy返回的是可变的。

可能有些人会问,array1我用NSMutableArray来定义不就可以么,他也不报错。但是结果不是你想的那样的,可能你觉得这样可行,但copy就要跟你过不去了。copy返回的指针是不可变的对象,如果你用NSMutableArray来定义array1,即NSmutableArray array1 = [array copy];用copy来复制对象,他返回的对象只能交给不可变的对象,你这样把他强扭过来,他还是不可变的。就像一块橡皮泥,你怎么捏各种形状出来,他还是一个橡皮泥,不可能变为一个蛋糕或者饼干。你想要返回一个可变对象,就只能使用mutablecopy。

这里就是copy和mutablecopy的区别。

 

复制对象里面还有一个很重要的东西就是深拷贝和浅拷贝。

深拷贝:除了拷贝对象本身之外,对象里面所包含的属性或者对象都一起拷贝

浅拷贝:只拷贝对象本身,对象里面所包含的属性或者对象不进行拷贝。

foundation框架中支持复制的对象都是默认浅拷贝,不对对象里面的属性和对象进行拷贝。

同样,我们先举一个foundation框架中的对象来证明下它默认的是浅拷贝:

 

NSMutableArray *array = [[NSArray alloc] init];

for(int i=0; i<3;i++) {

NSObject *obj = [[NSObject alloc] init];

[array addObject:obj];

[obj release];

}

 

for(NSObject *obj in array){

NSLog(@" 复制之前:%d", obj.retainCount);

}

 

NSArray *array1 = [array copy];

for(NSObject *obj in array){

NSLog(@" 复制之后:%d", obj.retainCount);

}

 

程序运行之后,我们可以看出数组array在复制之前和复制之后元素的引用计数都一样,所以我们可以证明foundation框架里面的对象默认是浅拷贝的。

 

 

我们来自定义一个对象,来理解下深拷贝:

 

@interface Person   //自定义对象要支持复制,必须实现NSCopying或者是NSMutableCopying协议

@proper(nontomic, retain) NString *name;

@proper(nontomic, retain) NSNumber *age;

@end

 

@implement Person

{

-(id)copywithzone:(NSZone*)zone {

Person *person = [[[self class] allocwithzone:zone] init];

person.name = [_name copy];

person.age = [_age copy];

return person;

}

 

}

@end

 

 

main.m

-autoreleasepool

{
   Person *person = [[Person alloc] init];

   NSLog(@"%d", person.name.retainCount);

   Person *person1 = [person copy];

NSLog(@"%d", person.name.retainCount);

}

 

程序执行后,发现复制前name的引用计数是1,复制后是2,对属性name进行了复制,这就是深拷贝。

 

0 0
原创粉丝点击