1、复制对象的基本概念
·复制对象的基本概念
复制对象顾名思义,复制一个对象作为副本,它会开辟一块新的内存(堆内存)来存储副本对象,就像复制文件一样。即源对象和副本对象是两块不同的内存区域。
对象具备复制功能,必须实现 :
·
<NSCopying>
协议
·<NSMutableCopying>
协议
·常用的可复制对象有:NSNumber、NSString、NSArray、NSDictionary、
NSMutableDictionary、NSMutableArray、NSMutableString
·复制对象的种类
·copy:产生对象的副本是不可变的
·mutableCopy:产生的对象副本是可变的
·创建一个数组(包含元素:one,two,three等),然后分别对它进行保留和拷贝操作,删除其中的一个元素,看看发生了什么?
//同块堆内存
NSMutableArray *array1 = [[NSMutableArrayalloc]initWithObjects:@"one",@"two",@"three",@"foure", nil];
NSMutableArray *array2 = [array1 retain];
[array2 removeLastObject];
NSLog(@"%@",array1);
NSLog(@"%ld",array1.retainCount);
//新的块堆内存
NSMutableArray *array1 = [[NSMutableArrayalloc]initWithObjects:@"one",@"two",@"three",@"foure", nil];
NSMutableArray *array2 = [array1 mutableCopy];
[array2 removeLastObject];
NSLog(@"%@",array1);
COPY和MUTABLECOPY的区别
·copy和mutableCopy的区别 ·前者返回一个不可变对象副本,后者返回一个可变对象副本
NSArray *array = [NSArray arrayWithObjects:@"aaa",@"bbb",@"ccc", nil];
//返回不可变数组
NSArray *arrayCopy = [array copy];
//返回可变数组
NSMutableArray *mutableCopy = [array mutableCopy];
[mutableCopy addObject:@"ddd"];
NSLog(@"arrayCopy: %@",arrayCopy);
NSLog(@"mutableCopy: %@",mutableCopy);
2、浅拷贝和深拷贝基本概念和用法
深浅复制的基本概念
·浅复制只复制对象的本身,对象里的属性、包含的对象不做复制。
·深复制则即复制对象本身,对象的属性也会复制一份。
·Foundation框架中支持复制的类,默认是浅复制。
例如: 一个数组包含了许多个对象,复制一个数组的副本,那么两个数组中的元素是没复制的,指向的还是同一个对象。
NSMutableArray *array = [NSMutableArray array];
for (int i=0; i<3; i++) {
NSObject *obj = [[NSObject alloc] init];
[array addObject:obj];
[obj release];
}
for (NSObject *obj in array) {
NSLog(@"指针地址:%p, 引用计数:%ld",obj,obj.retainCount);
}
NSArray *array2 = [array copy];
for (NSObject *obj in array2) {
NSLog(@"指针地址:%p, 引用计数:%ld",obj,obj.retainCount);
}
[array2 release];
3、对象的自定义拷贝
·对象拥有复制特性,须实现NSCopying、NSMutableCopying协议,实现该协议的copyWithZone:方法和mutableCopyWithZone:方法。
@interface Person : NSObject<NSCopying>
@property(nonatomic,copy)NSMutableString *name;
@property(nonatomic,retain)NSNumber *age;
@end
/********返回的是不可变对象**********/
- (id)copyWithZone:(NSZone *)zone {
User *user = [[[self class] allocWithZone:zone] init];
user.data = _data;
return user;
}
@interface Person : NSObject<NSMutableCopying>
@property(nonatomic,copy)NSMutableString *name;
@property(nonatomic,retain)NSNumber *age;
@end
/********返回的是可变对象**********/
- (id)mutableCopyWithZone:(NSZone *)zone {
UserMutable *user = [[[self class] allocWithZone:zone] init]; user.data = _data;
return user;
}
深、浅复制的不同实现
·Objective-C对象的深、浅拷贝的区别就在于你对copyWithZone的不同实现
- (id)copyWithZone:(NSZone *)zone {
/**浅复制的实现**/
Person *p = [[[self class] allocWithZone:zone] init];
p.name = _name;
p.age = _age;
return p;
}
- (id)copyWithZone:(NSZone *)zone {
/**深复制的实现**/
Person *p = [[[self class] allocWithZone:zone] init];
p.name = [_name copy];
p.age = [_age copy];
return p;
}
4、深、浅拷贝和RETAIN之间的总结
copy、mutableCopy和retain之间的关系
·Foundation可复制的对象,当我们copy的是一个不可变的对象时,它的作用相当于retain(cocoa做的内存优化)
·当我们使用mutableCopy时,无论源对象是否可变,副本是可变的,并且实现了真正意义上的拷贝
·当我们copy的是一个可变对象时,副本对象是不可变的,同样实现了真正意义上的拷贝
我们创建一个汽车类,汽车拥有一个Engine对象,一个车重和一个名字,实现下他的深复制和浅复制。
//Engine.h
#import <Foundation/Foundation.h>
@interface Engine : NSObject<NSCopying>
@end
//Engine.m
#import "Engine.h"
@implementation Engine
- (id)copyWithZone:(NSZone *)zone {
Engine *engine = [[[self class] allocWithZone:zone] init];
return engine;
}
- (void)dealloc {
NSLog(@"engine dealloc");
[super dealloc];
}
@end
//Car.h
#import <Foundation/Foundation.h>
@class Engine;
@interface Car : NSObject<NSCopying>
@property(nonatomic,retain)Engine *engine;
@property(nonatomic,retain)NSNumber *weight;
@property(nonatomic,copy)NSString *name;
@end
//Car.m
#import "Car.h"
#import "Engine.h"
@implementation Car
- (id)copyWithZone:(NSZone *)zone {
/***浅拷贝**/
Car *car = [[[self class] allocWithZone:zone] init];
car.engine = _engine;
car.weight = _weight;
car.name = _name;
/***深拷贝**/
// Car *car = [[[self class] allocWithZone:zone] init];
// Engine *engine = [_engine copy];
// NSNumber *weight = [_weight copy];
// NSString *name = [_name copy];
//
// car.engine = engine;
// car.weight = weight;
// car.name = name;
//
// [engine release];
// [weight release];
// [name release];
return car;
}
- (void)dealloc {
NSLog(@"car dealloc");
[_weight release];
[_name release];
[_engine release];
[super dealloc];
}
@end
//main.m
#import <Foundation/Foundation.h>
#import "Car.h"
#import "Engine.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
Car *car = [[Car alloc] init];
Engine *engine = [[Engine alloc] init];
car.engine = engine;
[engine release];
car.name = @"奥迪";
car.weight = @1000;
Car *car2 = [car copy];
NSLog(@"car:%@, car2:%@",car,car2);
[car release];
[car2 release];
}
return 0;
}