iOS - 深复制和浅复制

来源:互联网 发布:医疗网络咨询 编辑:程序博客网 时间:2024/05/16 15:45
一、copy与retain的区别:
1、copy是创建一个新对象,retain是创建一个指针,引用对象计数加一。
2、copy属性表示两个对象内容相同,新的对象retain为1,与旧有的对象的引用计数无关,旧有对象没有改变。copy减少对象对上下文的依赖。
3、retain属性表示两个对象地址相同(建立一个指针,指针拷贝),内容相同,这个对象的retain值加1,也就是说retain是指针拷贝,copy是内容拷贝。

二、copy、mutableCopy
1、必须遵守NSCopying协议的类可以发送copy消息,遵守NSMutableCopying协议的类可以发送mutableCopying消息。
2、默认的ios类并没有遵守这两个协议,如果想自定义一下copy,那么就必须遵守NSCopying并实现copyWithZone:方法,如果想自定义一下mutableCopy,那么久必须遵守NSMutableCopying并实现mutableCopyWithZone:方法。
3、iOS提供了copy和mutableCopy方法,copy就是复制一个不可变的对象,mutableCopy就是复制一个可变的对象。
4、例1:系统的非容器类对象:NSString、NSNumber等等的一类对象
NSString *string = @“origin”;
NSString *stringCopy = [string copy];
NSMutableString *stringMutCopy = [string mutableCopy];
[stringMutCopy appendString:@“!!”];
查看内存可以发现,string和stringCopy指向的是同一块内存区域(又叫apple弱引用weak reference),此时stringCopy的引用计数和strong的一样都为2.二strongMutCopy则是我们所说的真正意义上的复制,系统为其分配了新的内存,但指针指向的字符串还是和strong所指的一样。
NSMutableString *string  = [NSMutableString stringWithString:@“hello”];
NSString *stringCopy = [string copy];
NSMutableString *mStringCopy = [string copy];
NSMutableString *mutStrCopy = [string mutableCopy];
[string appendString:@“^-^”];
[mStringCopy appendString:@“^-^”];//error
[mutStrCopy appendString:@“^-^”];
以上四个NSString对象所分配的内存都是不一样的。但是对于mStringCopy其实是个不可变的对象,所以上述会报错。
对于系统的非容器类对象,我们可以认为,如果对一不可变对象复制,copy是指针复制(浅拷贝),mutableCopy是对象复制(深拷贝)。如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。
例2:系统容器类对象(指的是NSArray、NSDictionary等)
copy返回不可变对象,mutableCopy返回的是可变对象。
NSArray *array = [NSArray arrayWithObjects:@“a”,@“b”,@“c”,nil];
NSArray *arrayCopy = [array copy];
//arrayCopy和array同一个NSArray对象(指向相同的对象),包括array里面的元素也是指向相同的指针

三、必须使用深拷贝:
[array addObject:obj];//这样obj的引用计数会加一,如果使用remove则obj的引用计数会减一
iOS 对集合的内存处理就是这样的:
假设obj只被array拥有:id temp = [array objectAtIndex:0];
[array removeObjectAtIndex:0];
如果你在要使用temp就会出错,因为这个时候obj已经被释放了。
由于在程序中经常会遇到集合类的传值,所以,简单的retain未必够用,需要对集合内容的拷贝,也就是深拷贝。

四、可复制对象
NSNumber、NSString、NSArray、NSDictionary、NSMutableDictionary、NSMutableArray、NSMutableString。

五、复制对象的基本概念
1、copy方法用于复制对象的不可变副本。通常来说,copy方法总是返回对象的不可修改的副本,即使该对象本身是可修改的。例如:程序调用了NSMutableString的copy方法,将会返回不可修改的字符床对象。
2、mutableCopy方法用于复制对象的可变副本。通常来说,mutableCopy方法总是返回该对象的可修改的副本,即使该对象本身不可修改的,调用mutableCopy方法复制出来的副本也是可以修改的。例如:程序调用了NSString的mutableCopy方法,将会返回一个NSMutableString对象。

六、复制对象
例1:
NSArray *array1 = @[@"one",@"two",@"three",@"four",@"five"];
//使用copy复制一份array1对象的不可变的副本
NSMutableArray *mutArray = [array1 copy];

//下面这行代码会报错,因为mutAray是不可修改的,编译时类型是NSMutableArray,运行时实际上却变成了NSArray类型
[mutArray addObject:@"test"];

例2:
NSMutableArray *mutArray = [NSMutableArray arrayWithObjects:@"张三",@"李四",@"王五",nil];
//使用mutTableCopy复制一份mutArray对象的可修改的副本
NSArray *array = [mutArray mutableCopy];
//下面这行代码可以正确执行,因为arrat实际上是可修改的数组,编译时类型为NSArray,运行时实际上却变成了NSMutableArray类型
因此可以强转成NSMutableArray类型,同样可以正确调用addObject方法
[(NSMutableArray *)array addObject:@"赵六"];
NSLog(@"%li",array.count);

七、浅拷贝和深拷贝的概念
浅拷贝(shallow copy),当对象的属性是指针变量时,如果程序只是复制该指针的地址,而不是真正复制指针所指向的对象,这种方式被称为浅拷贝。

深拷贝(deep copy),深拷贝不仅会复制对象本身,而且会“递归”复制每个指针类型的属性,直到两个对象没有任何的共用部分为止。

八、代码示例:
.h

@property (nonatomic,strong)NSMutableString *userName;

@property (nonatomic,strong)NSString *userPwd;

@property (nonatomic,assign)int userAge;

-(id)initWithName:(NSMutableString *)userName withPwd:(NSString *)userPwd;

@end


.m

-(id)initWithName:(NSMutableString *)userName withPwd:(NSString *)userPwd{

    if (self = [superinit]) {

        _userName = userName;

        _userPwd = userPwd;

    }

    return self;

}

-(NSString *)description

{

    return [NSStringstringWithFormat:@"userName is %@ \nuserPwd is %@",_userName,_userPwd];

}

-(id)copyWithZone:(NSZone *)zone

{

    //开辟了一块新的内存空间

    UserInfo *userInfo = [[UserInfoallocWithZone:zone]init];

    //给新的userInfo对象赋值

    //将已有的值赋给userInfo

    /*

     是深拷贝还是浅拷贝看copyWithZone

     这句话userInfo.userName = _userName;

     相当于userInfo.userName = [_userName retain];是浅拷贝。

     浅拷贝:当对象的属性是指针变量时,如果程序只是复制该指针的地址,而不是真正的复制指针所指向的对象,这种方式被称为浅拷贝。

     浅拷贝的隐患:改变副本对象后会改变本来的对象的值。

     

     当是userInfo.userName = [_userName copy];是深拷贝.

     深拷贝是不仅会复制对象本身,而且每个对象的每个属性都递归复制每个指针类型的属性,直到两个对象没有任何的共用部分为止

     如果是基本数据类型的话,不需要加copy,如:userInfo.userAge = _userAge;

     */

//    userInfo.userName = _userName;

//    userInfo.userPwd = _userPwd;

    userInfo.userName = [_userNamemutableCopy];

    userInfo.userPwd = [_userPwdcopy];

    userInfo.userAge = _userAge;

    return userInfo;

}




注:

 @property参数使用小结:

 1》使用IBOutlet属性的控件用weak

 提示:在纯手写代码实现的界面布局时,如果通过懒加载处理界面控件,需要使用strong强指针

 

 2》属性对象用strong(当该对象需要被拷贝的话,就用copy

 

 3》基本数据类型用assign

 

 4》字符串NSStringcopyNSMutableString不能使用copy@property没有提供mutableCopy,只有copy,只能用strong



0 0
原创粉丝点击