一、要了解浅拷贝与深拷贝,首要的是理解浅拷贝是什么,深拷贝是什么。数组
<1>浅拷贝:就至关于retain,只copy了一个对象的引用,和自己是同一个对象,就至关于影子。atom
<2>深拷贝:重新开辟了一块内存空间,用来存放原来对象里面的东西,这个时候,copy出来的对象和原来的对象不是同一个对象,他们的内容同样,就至关于克隆人。spa
<3>拷贝出来的的对象是什么类型取决于使用什么拷贝。3d
二、拷贝的用法code
<1>不可变copy拷贝不可变对象(浅拷贝):对象
NSArray *array=[[NSArray alloc]initWithObjects:@"1",@"2", nil]; NSArray *array1=[array copy]; NSLog(@"array1=%@",array1); NSLog(@"array=%p,array1=%p",array,array1); NSLog(@"array = %lu ,array1 = %lu",[array retainCount],[array1 retainCount]);
其输出结果:blog
看输出结果反馈出:对不可变数组array进行不可变copy时,拷贝出来的array1是跟array同样的对象且两个数组的引用计数都+1,至关于对array自己的一个引用而已。内存
<2>不可变copy拷贝可变对象(深拷贝):it
NSMutableArray *mArray=[[NSMutableArray alloc]initWithObjects:@"1",@"2", nil]; NSArray *array=[mArray copy]; NSLog(@"mArray=%p,array=%p",mArray,array); NSLog(@"array=%@",array); NSLog(@"array的类型%@",[array class]); NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);
其输出结果:io
看输出结果反馈出:对可变数组mArray进行不可变copy操做,拷贝出来的array数组与mArray数组的内存地址是不同的且两块内存地址内容是相同的,而内容是同样的且引用计数不发生改变,array数组的类型不变依旧是不可变数组。由此能够得出不可变copy拷贝可变对象是深拷贝。
<3>可变copy拷贝不可变对象(深拷贝):
NSArray *array=[[NSArray alloc]initWithObjects:@"1",@"2", nil]; NSMutableArray *mArray=[array mutableCopy]; NSLog(@"-%@",[[array mutableCopy] class]); NSLog(@"array=%p,mArray=%p",array,mArray); NSLog(@"mArray=%@",mArray); NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);
其输出结果:
看输出结果反馈出:对不可变数组array进行可变可变copy操做,拷贝出来的mArray数组与array数组的内存地址不一样且两块内存地址内容是相同的,且拷贝出来的对象是可变的,引用计数并无发生改变,由此能够得出可变copy拷贝不可变对象是深拷贝。
<4>可变copy拷贝可变对象(深拷贝):
NSMutableArray *mArray=[[NSMutableArray alloc]initWithObjects:@"1",@"2", nil]; NSMutableArray *array=[mArray mutableCopy]; NSLog(@"%@",[[mArray mutableCopy] class]); NSLog(@"mArray=%p,array=%p",mArray,array); NSLog(@"array=%@",array); NSLog(@"mArray = %lu ,array = %lu",[mArray retainCount],[array retainCount]);
其输出结果:
看输出结果反馈出:对可变数组array进行可变可变copy操做,拷贝出来的array数组与mArray数组的内存地址不一样且两块内存地址内容是相同的,且拷贝出来的对象是可变的,没有引发引用计数的变化,由此能够得出可变copy拷贝可变对象是深拷贝。
<5>自定义类的copy:
自定义一个person类
.h文件
#import <Foundation/Foundation.h> //要实现copy必须遵照NSCopying或者NSMutableCopying协议,这里面有一个必须实现的协议copyWithZone: @interface Person : NSObject<NSCopying> @property(retain,nonatomic)NSString *name; @property(copy,nonatomic)NSArray *array; @property(copy,nonatomic)NSMutableArray *mArray; @end
.m文件
#import "Person.h" @implementation Person -(id)copyWithZone:(NSZone *)zone { Person *pp=[[Person alloc]init]; // NSLog(@"pp=%p",pp); pp.name=self.name; return pp; } @end
在main.m文件中,导入person类头文件且添加下列代码
/* 要实现copy必须遵照NSCopying或者NSMutableCopying协议,这里面有一个必须实现的协议copyWithZone: */ Person *p=[[Person alloc]init]; p.name=@"张三"; Person *p1=[p copy]; NSLog(@"p=%p,p1=%p",p,p1); NSLog(@"p1的名字为%@",p1.name);
运行结果获得:
能够得出:自定义对象进行copy操做获得的是两块补同样的内存地址,且内容是同样的。
<6>属性的copy:
1、copy修饰不可变属性的时候,就至关于retain
2、copy修饰可变属性的时候,至关于不可变copy拷贝可变对象。属于深拷贝,这个时候,属性和对属性赋值的对象的内存都须要单独管理
3、建议对象类型都是用retain