淺拷貝:拷貝指向原來對(duì)象的指針,使原對(duì)象的引用計(jì)數(shù)+1,可以理解為創(chuàng)建了一個(gè)指向原對(duì)象的新指針而已,并沒有創(chuàng)建一個(gè)全新的對(duì)象。

NSString *str1 = @"str1";
NSString *str2 = [str1 copy];
NSLog(@"\nstr1 = %@ str1P = %p \n str2 = %@ str2P = %p", str1, str1, str2, str2);
/*輸出結(jié)果
str1 = str1 str1P = 0x104d75180
str2 = str1 str2P = 0x104d75180
*/
深拷貝:拷貝出和原來僅僅是值一樣,但是內(nèi)存地址完全不一樣的新的對(duì)象,創(chuàng)建后和原對(duì)象沒有任何關(guān)系。

NSMutableString *mStr1 = [NSMutableString stringWithString:@"123"];
NSMutableString *mStr2 = [mStr1 mutableCopy];
NSLog(@"\n mStr1 = %@ mStr1P = %p \n mStr2 = %@ mStr2P = %p", mStr1, mStr1, mStr2, mStr2);
/*輸出結(jié)果
mStr1 = 123 mStr1P = 0x6000004460c0
mStr2 = 123 mStr2P = 0x600000446420
*/
開辟了新的內(nèi)存空間
可變對(duì)象NSMutableString
- (void) mutableNSStringTest
{
NSMutableString *mstr1 = [NSMutableString stringWithString:@"test002"];
NSMutableString *mstr2 = [mstr1 copy];
//[str2 appendString:@"test"]; //copy返回的是不可變對(duì)象,mstr2不能被修改,因此會(huì)發(fā)生崩潰
NSMutableString *mstr3 = [mstr1 mutableCopy];
[mstr3 appendString:@"modify"];
NSLog(@"mstr1:%p - %@ \r\n",mstr1,mstr1);
NSLog(@"mstr2:%p - %@ \r\n",mstr2,mstr2);
NSLog(@"mstr3:%p - %@ \r\n",mstr3,mstr3);
}
2017-07-20 18:14:35.789 beck.wang[1433:180881] mstr1:0x610000075e40 - test002
2017-07-20 18:14:35.790 beck.wang[1433:180881] mstr2:0xa323030747365747 - test002
2017-07-20 18:14:35.790 beck.wang[1433:180881] mstr3:0x610000074480 - test002modify
分析:mstr1、mstr2、mstr3 地址都不同,NSMutableString對(duì)象copy與mutableCopy都是深拷貝,且copy返回的對(duì)象是不可變對(duì)象。
總結(jié)一波:copy不可變對(duì)象時(shí)是淺拷貝,copy可變對(duì)象時(shí)是深拷貝,mutableCopy是深拷貝
再來看一段代碼
NSString *str1 = @"str1";
NSString *str2 = [str1 copy];
str1 = @"asdf";
NSLog(@"\nstr1 = %@ str1P = %p \n str2 = %@ str2P = %p", str1, str1, str2, str2);
/*輸出結(jié)果,修改str2 同理
str1 = asdf str1P = 0x10776b1a0
str2 = str1 str2P = 0x10776b180
*/
這里不是說copy是淺拷貝嗎?str1 和 str2 指向同一個(gè)內(nèi)存空間,str1變化,str2的值也會(huì)變化。
但是copy還有它的特點(diǎn):
修改源對(duì)象的屬性和行為,不會(huì)影響副本對(duì)象
修改副本對(duì)象的屬性和行為,不會(huì)影響源對(duì)象
自定義類實(shí)現(xiàn)copy的步驟:
(1)遵守NSCoping協(xié)議
(2)實(shí)現(xiàn)copyWithZone方法。//參數(shù)zone基本不用,它的意思是指定該方法從始至終都在某一個(gè)區(qū)域分配內(nèi)存
(所有copy最終都會(huì)調(diào)用這個(gè)方法)
{
//方法內(nèi)部進(jìn)行以下操作
//(1)實(shí)例化對(duì)象
A* a = [A alloc ]init]; //一般正規(guī)寫法是[[self.class alloc] init] 因?yàn)檫@樣子類也可以復(fù)用該方法
//(2)給屬性賦值
a.xx = xx;
//(3)返回新對(duì)象
return a;
}
#import <Foundation/Foundation.h>
/*
創(chuàng)建一個(gè)Teacher類,并讓該類實(shí)現(xiàn)copy方法
*/
//1.遵守NSCopying協(xié)議
@interface Teacher : NSObject<NSCopying>
@property(nonatomic,copy)NSString* name;
//2.實(shí)現(xiàn)copyWithZone方法;
-(id)copyWithZone:(NSZone *)zone;
@end
#import "Teacher.h"
@implementation Teacher
//實(shí)現(xiàn)copyWithZone方法
-(id)copyWithZone:(NSZone *)zone
{
Teacher* teacher = [[self.class alloc]init];
teacher.name = self.name;
return teacher;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
Teacher* teacher = [[Teacher alloc]init];
teacher.name = @"我是園丁";
Teacher* teacher1 = [teacher copy];
NSLog(@"teacher:%p-%@",teacher,teacher.name);
NSLog(@"teacher1:%p-%@",teacher1,teacher1.name);
}
運(yùn)行結(jié)果:
2015-08-15 16:41:07.821 copy的那些事[1779:148657] teacher:0x7fd750d13ce0-我是園丁
2015-08-15 16:41:07.822 copy的那些事[1779:148657] teacher1:0x7fd750d13cf0-我是園丁
上面代碼如果沒有實(shí)現(xiàn)NSCopying協(xié)議,-[Person copyWithZone:]: unrecognized selector sent to instance 0x60000022b6a0