Java基本数据类型 Java Out Of Memory Mxnet 百度搜索优化 golang grails sass tcp routes Amaze UI Plupload vue插件库 pmp学习视频 软件测试实战项目 oracle查看数据库 excel动态图表制作 js空格符 css选择器有几种 ln函数图像 python教学 mysql查询 python正则提取字符串 python3下载安装 python配置环境 python入门教程 python或运算 python下载安装教程 java获取现在时间 学java基础 java包名 linux命令 tmac修改器 windows7loader unix操作系统下载 java小程序 adobe清理工具 vnc客户端 cms教程 摩尔斯电码翻译器在线 掌门一对一下载
当前位置: 首页 > 学习教程  > 编程学习

iOS深拷贝浅拷贝

2021/1/9 2:04:52 文章标签: 深浅拷贝

转自:http://mobile.51cto.com/iphone-267060.htm iPhone开发语言Objective-C是一种简单的计算机语言,简称OC,支持复杂南通的面向对象编程。Objective C语言,通常写作ObjC和较少用的Objective C或Obj-C,是扩充C的面向对…

转自:http://mobile.51cto.com/iphone-267060.htm

iPhone开发语言Objective-C是一种简单的计算机语言,简称OC,支持复杂南通的面向对象编程。Objective C语言,通常写作ObjC和较少用的Objective C或Obj-C,是扩充C的面向对象编程语言。它主要使用于Mac OS X和GNUstep这两个使用OpenStep标准的系统,而在NeXTSTEP和OpenStep中它更是基本语言。Objective C可以在gcc运作的系统写和编译,因为gcc含Objective C的编译器。

在ObjectiveC 中,什么是深浅拷贝? 深浅拷贝分别指深拷贝和浅拷贝,即mutableCopy和copy方法。

copy复制一个不可变对象,而mutableCopy复制一个mutable可变对象。

什么时候用到深浅拷贝?下面举几个例子说明。 非容器类对象 如NSString,NSNumber等一类对象  

示例1:

 
  1. // 非容器类对象     NSString *str = @"origin string";  
  2.    NSString *strCopy = [str copy];  
  3.    NSMutableString *mstrCopy = [str mutableCopy];  
  4.    [mstrCopy appendString:@"??"]; 

查看内存可以发现,str和strCopy指向的是同一块内存区域,我们称之为弱引用(weak reference)。而mstrCopy是真正的复制,系统为其分配了新内存空间,保存从str复制过来的字符串值。从最后一行代码中修改这些值而不影响str和strCopy中可证明。

示例2:

 
  1. NSMutableString *mstr = [NSMutableString stringWithString:@"origin"];  
  2.    NSString *strCopy = [mstr copy];  
  3.    NSMutableString *mstrCopy = [mstr copy];  
  4.    NSMutableString *mstrMCopy = [mstr mutableCopy];  
  5.    //[mstrCopy appendString:@"1111"];  //error  
  6.    [mstr appendString:@"222"];  
  7.    [mstrMCopy appendString:@"333"]; 

以上四个对象所分配的内存都是不一样的。而且对于mstrCopy,它所指向的其实是一个imutable对象,是不可改变的,所以会出错。这点要注意,好好理解。

容器类对象深浅复制

比如NSArray,NSDictionary等。对于容器类本身,上面讨论的结论也适用的,下面探讨的是复制后容器内对象的变化。

示例3

 
  1. /* copy返回不可变对象,mutablecopy返回可变对象 */   
  2.  
  3.       
  4.     NSArray *array1     = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];  
  5.     NSArray *arrayCopy1 = [array1 copy];  
  6.     //arrayCopy1是和array同一个NSArray对象(指向相同的对象),包括array里面的元素也是指向相同的指针  
  7.     NSLog(@"array1 retain count: %d",[array1 retainCount]);  
  8.     NSLog(@"array1 retain count: %d",[arrayCopy1 retainCount]);  
  9.       
  10.     NSMutableArray *mArrayCopy1 = [array1 mutableCopy];  
  11.     //mArrayCopy1是array1的可变副本,指向的对象和array1不同,但是其中的元素和array1中的元素指向的还是同一个对象。mArrayCopy1还可以修改自己的对象  
  12.     [mArrayCopy1 addObject:@"de"];  
  13.     [mArrayCopy1 removeObjectAtIndex:0]; 

array1和arrayCopy1是指针复制,而mArrayCopy1是对象复制,符合前面示例1讨论的结论。mArrayCopy1可以改变其内的元素:删除或添加。但容器内的元素内容都是浅拷贝。

示例4

 
  1. NSArray *mArray1 = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];  
  2.     NSLog(@"mArray1 retain count: %d",[mArray1 retainCount]);  
  3.     NSArray *mArrayCopy2 = [mArray1 copy];  
  4.     NSLog(@"mArray1 retain count: %d",[mArray1 retainCount]);  
  5.     // mArray1和mArrayCopy2指向同一对象,retain值+1。  
  6.       
  7.     NSMutableArray *mArrayMCopy1 = [mArray1 mutableCopy];  
  8.     NSLog(@"mArray1 retain count: %d",[mArray1 retainCount]);     //mArrayCopy2和mArray1指向的是不一样的对象,但是其中的元素都是一样的对象——同一个指针  
  9.  
  10.     NSMutableString *testString = [mArray1 objectAtIndex:0];   
  11.  
  12.     //testString = @"1a1";//这样会改变testString的指针,其实是将@“1a1”临时对象赋给了testString  
  13.     [testString appendString:@" tail"];//这样以上三个数组的首元素都被改变了 

由此可见,对于容器而言,其元素对象始终是指针复制。如果需要元素对象也是对象复制,就需要实现深拷贝。http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Collections/Articles/Copying.html

示例5

 
  1. NSArray *array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"first"],[NSStringstringWithString:@"b"],@"c",nil];  
  2.    NSArray *deepCopyArray=[[NSArray alloc] initWithArray: array copyItems: YES];  
  3.    NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:  
  4.    [NSKeyedArchiver archivedDataWithRootObject: array]]; 

trueDeepCopyArray是完全意义上的深拷贝,而deepCopyArray则不是,对于deepCopyArray内的不可变元素其还是指针复制。

或者我们自己实现深拷贝的方法。因为如果容器的某一元素是不可变的,那你复制完后该对象仍旧是不能改变的,因此只需要指针复制即可。除非你对容器内的元素重新赋值,否则指针复制即已足够。

举个例子,[[array objectAtIndex:0]appendstring:@”sd”]后其他的容器内对象并不会受影响。[[array objectAtIndex:1]和[[deepCopyArray

objectAtIndex:0]尽管是指向同一块内存,但是我们没有办法对其进行修改——因为它是不可改变的。所以指针复制已经足够。所以这并不是完全意义上的深拷贝。

自己实现深拷贝的方法

NSDictionaryMutableDeepCopy.h
 

 
  1. 8 #import <foundation /Foundation.h> 
  2. @interface NSDictionary(MutableDeepCopy)  
  3. - (NSMutableDictionary *)mutableDeepCopy;  
  4. @end  
  5. </foundation> 
  6. NSDictionaryMutableDeepCopy.m  
  7. #import "NSDictionaryMutableDeepCopy.h"  
  8. @implementation NSDictionary(MutableDeepCopy)  
  9. - (NSMutableDictionary *)mutableDeepCopy {  
  10.     NSMutableDictionary *ret = [[NSMutableDictionary alloc]  
  11.                                 initWithCapacity:[self count]];  
  12.     NSArray *keys = [self allKeys];  
  13.     for (id key in keys) {  
  14.         id oneValue = [self valueForKey:key];  
  15.         id oneCopy = nil;          
  16.         if ([oneValue respondsToSelector:@selector(mutableDeepCopy)]) {  
  17.             oneCopy = [oneValue mutableDeepCopy];  
  18.         }  
  19.         else if ([oneValue respondsToSelector:@selector(mutableCopy)]) {  
  20.             oneCopy = [oneValue mutableCopy];  
  21.         }  
  22.         if (oneCopy == nil) {  
  23.             oneCopy = [oneValue copy];  
  24.         }  
  25.         [ret setValue:oneCopy forKey:key];  
  26.     }  
  27.     return ret;  
  28. }  
  29. @end 

使用类别方法来实现。

自定义对象  

如果是我们定义的对象,那么我们自己要实现NSCopying,NSMutableCopying这样就能调用copy和mutablecopy了。举个例子:

 
  1. @interface MyObj : NSObject<nscopying ,NSMutableCopying> 
  2. {  
  3.          NSMutableString *name;  
  4.          NSString *imutableStr;  
  5.          int age;  
  6. }  
  7. @property (nonatomic, retain) NSMutableString *name;  
  8. @property (nonatomic, retain) NSString *imutableStr;  
  9. @property (nonatomic) int age;  
  10.    
  11. @end  
  12.  
  13. @implementation MyObj  
  14. @synthesize name;  
  15. @synthesize age;  
  16. @synthesize imutableStr;  
  17. - (id)init  
  18. {  
  19.          if (self = [super init])  
  20.          {  
  21.                    self.name = [[NSMutableString alloc]init];  
  22.                    self.imutableStr = [[NSString alloc]init];  
  23.                    age = -1;  
  24.          }  
  25.          return self;  
  26. }  
  27. - (void)dealloc  
  28. {  
  29.          [name release];  
  30.          [imutableStr release];  
  31.          [super dealloc];  
  32. }  
  33. - (id)copyWithZone:(NSZone *)zone  
  34. {  
  35.          MyObj *copy = [[[self class] allocWithZone:zone] init];  
  36.          copy->name = [name copy];  
  37.          copy->imutableStr = [imutableStr copy];  
  38. //       copy->name = [name copyWithZone:zone];;  
  39. //       copy->imutableStr = [name copyWithZone:zone];//  
  40.          copy->ageage = age;  
  41.    
  42.          return copy;  
  43. }  
  44. - (id)mutableCopyWithZone:(NSZone *)zone  
  45. {  
  46.          MyObj *copy = NSCopyObject(self, 0, zone);  
  47.          copy->name = [self.name mutableCopy];  
  48.          copy->ageage = age;  
  49.          return copy;  
  50. }  
  51. @end  
  52. </nscopying> 

本文链接: http://www.dtmao.cc/news_show_1100288.shtml

附件下载

相关教程

    暂无相关的数据...

共有条评论 网友评论

验证码: 看不清楚?