ios深拷贝,浅拷贝,拷贝自定义对象的简单介绍

copy语法的目的:改变副本的时候,不会影响到源对象;

深拷贝:内容拷贝,会产生新的对象。新对象计数器置为1,源对象计数器不变。

浅拷贝:指针拷贝,不会产生新的对象。源对象计数器+1

拷贝有下面两个方法实现拷贝:

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. - (id)copy;  
  2. - (id)mutableCopy;  

要实现copy,必须实现<NSCopying>协议
数组,字典,字符串都已经实现了<NSCopying>协议,以下以字符串为例,其他的同理:

1.不可变字符串调用copy实现拷(浅拷贝)

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. NSString *string = [[NSString alloc] initWithFormat:@"abcde"];  
  2. // copy产生的是不可变副本,由于源对象本身就不可变,所以为了性能着想,copy会直接返回源对象本身  
  3. // 源对象计数器会+1  
  4. // 在浅拷贝情况下,copy其实就相当于retain  
  5. NSString *str = [string copy];  

2.不可变字符串调用mutableCopy实现拷贝,(深拷贝)

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. NSString *string = [[NSString alloc] initWithFormat:@"abcd"];  
  2. // 产生了一个新的对象,计数器为1。源对象的计数器不变。  
  3. NSMutableString *str = [string mutableCopy];//此时存在两个对象// str:1和// string:1  
  4.  // str和string不是相同对象  
  5.  // NSLog(@"%i", str == string);//0  
  6.  [str appendString:@" abcd"];//修改str不影响string  
  7.  NSLog(@"string:%@", string);  
  8.  NSLog(@"str:%@", str);  

3.可变字符串调用copy实现拷贝(深拷贝)

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10];  
  2.  // 会产生一个新对象,str计数器为1  
  3.  NSString *str = [string copy];  

4. 可变字符串的 MutableCopy (深拷贝)

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10];  
  2. // 会产生一个新对象,str计数器为1  
  3. NSMutableString *str = [string mutableCopy];  
  4. [str appendString:@"1234"];//修改新对象不影响原对象  
  5. NSLog(@"str:%@", str);  
  6. NSLog(@"string:%@", string);  


5.拷贝自定义对象,下面以Student对象为例

a.Student要实现copy,必须实现<NSCopying>协议

b.实现<NSCopying>协议的方法:

- (id)copyWithZone:(NSZone *)zone

Student.h文件

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. @interface Student : NSObject <NSCopying>  
  2.   
  3. // copy代表set方法会release旧对象、copy新对象  
  4. // 修改外面的变量,并不会影响到内部的成员变量  
  5. // 建议:NSString一般用copy策略,其他对象一般用retain  
  6. @property (nonatomiccopyNSString *name;  
  7.   
  8. + (id)studentWithName:(NSString *)name;  
  9.   
  10. @end  

Student.m文件

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #import "Student.h"  
  2.   
  3. @implementation Student  
  4.   
  5. + (id)studentWithName:(NSString *)name {  
  6.     // 这里最好写[self class]  
  7.     Student *stu = [[[[self class] alloc] init] autorelease];  
  8.     stu.name = name;  
  9.       
  10.     return stu;  
  11. }  
  12.   
  13. - (void)dealloc {  
  14.     [_name release];  
  15.       
  16.     [super dealloc];  
  17. }  
  18.   
  19. #pragma mark description方法内部不能打印self,不然会造成死循环  
  20. - (NSString *)description {  
  21.     return [NSString stringWithFormat:@"[name=%@]", _name];  
  22. }  
  23.   
  24. #pragma mark copying协议的方法  
  25. // 这里创建的副本对象不要求释放  
  26. - (id)copyWithZone:(NSZone *)zone {  
  27.     Student *copy = [[[self class] allocWithZone:zone] init];  
  28.       
  29.     // 拷贝名字给副本对象  
  30.     copy.name = self.name;  
  31.       
  32.     return copy;  
  33. }  
  34.   
  35. @end  

拷贝Student

[objc]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Student *stu1 = [Student studentWithName:@"stu1"];  
  2.   
  3. Student *stu2 = [stu1 copy];  
  4. stu2.name = @"stu2";  
  5.   
  6. NSLog(@"stu1:%@", stu1);  
  7. NSLog(@"stu2:%@", stu2);  
  8.   
  9. [stu2 release];  


.小结:

建议:NSString一般用copy策略,其他对象一般用retain;

只有一种情况是浅拷贝:不可变对象调用copy方法时,其他情况都为深拷贝;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值