`

ObjectiveC 深浅拷贝(mutableDeepCopy)学习

 
阅读更多

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

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

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

示例1:

  1. //非容器类对象NSString*str=@"originstring";
  2. NSString*strCopy=[strcopy];
  3. NSMutableString*mstrCopy=[strmutableCopy];
  4. [mstrCopyappendString:@"??"];

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

示例2:

  1. NSMutableString*mstr=[NSMutableStringstringWithString:@"origin"];
  2. NSString*strCopy=[mstrcopy];
  3. NSMutableString*mstrCopy=[mstrcopy];
  4. NSMutableString*mstrMCopy=[mstrmutableCopy];
  5. //[mstrCopyappendString:@"1111"];//error
  6. [mstrappendString:@"222"];
  7. [mstrMCopyappendString:@"333"];

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

容器类对象深浅复制

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

示例3

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

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

示例4

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

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

示例5

  1. NSArray*array=[NSArrayarrayWithObjects:[NSMutableStringstringWithString:@"first"],[NSStringstringWithString:@"b"],@"c",nil];
  2. NSArray*deepCopyArray=[[NSArrayalloc]initWithArray:arraycopyItems:YES];
  3. NSArray*trueDeepCopyArray=[NSKeyedUnarchiverunarchiveObjectWithData:
  4. [NSKeyedArchiverarchivedDataWithRootObject:array]];

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

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

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

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

自己实现深拷贝的方法

NSDictionaryMutableDeepCopy.h

  1. 8#import<foundation/Foundation.h>
  2. @interfaceNSDictionary(MutableDeepCopy)
  3. -(NSMutableDictionary*)mutableDeepCopy;
  4. @end
  5. </foundation>
  6. NSDictionaryMutableDeepCopy.m
  7. #import"NSDictionaryMutableDeepCopy.h"
  8. @implementationNSDictionary(MutableDeepCopy)
  9. -(NSMutableDictionary*)mutableDeepCopy{
  10. NSMutableDictionary*ret=[[NSMutableDictionaryalloc]
  11. initWithCapacity:[selfcount]];
  12. NSArray*keys=[selfallKeys];
  13. for(idkeyinkeys){
  14. idoneValue=[selfvalueForKey:key];
  15. idoneCopy=nil;
  16. if([oneValuerespondsToSelector:@selector(mutableDeepCopy)]){
  17. oneCopy=[oneValuemutableDeepCopy];
  18. }
  19. elseif([oneValuerespondsToSelector:@selector(mutableCopy)]){
  20. oneCopy=[oneValuemutableCopy];
  21. }
  22. if(oneCopy==nil){
  23. oneCopy=[oneValuecopy];
  24. }
  25. [retsetValue:oneCopyforKey:key];
  26. }
  27. returnret;
  28. }
  29. @end

使用类别方法来实现。

自定义对象

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

  1. @interfaceMyObj:NSObject<nscopying,NSMutableCopying>
  2. {
  3. NSMutableString*name;
  4. NSString*imutableStr;
  5. intage;
  6. }
  7. @property(nonatomic,retain)NSMutableString*name;
  8. @property(nonatomic,retain)NSString*imutableStr;
  9. @property(nonatomic)intage;
  10. @end
  11. @implementationMyObj
  12. @synthesizename;
  13. @synthesizeage;
  14. @synthesizeimutableStr;
  15. -(id)init
  16. {
  17. if(self=[superinit])
  18. {
  19. self.name=[[NSMutableStringalloc]init];
  20. self.imutableStr=[[NSStringalloc]init];
  21. age=-1;
  22. }
  23. returnself;
  24. }
  25. -(void)dealloc
  26. {
  27. [namerelease];
  28. [imutableStrrelease];
  29. [superdealloc];
  30. }
  31. -(id)copyWithZone:(NSZone*)zone
  32. {
  33. MyObj*copy=[[[selfclass]allocWithZone:zone]init];
  34. copy->name=[namecopy];
  35. copy->imutableStr=[imutableStrcopy];
  36. //copy->name=[namecopyWithZone:zone];;
  37. //copy->imutableStr=[namecopyWithZone:zone];//
  38. copy->ageage=age;
  39. returncopy;
  40. }
  41. -(id)mutableCopyWithZone:(NSZone*)zone
  42. {
  43. MyObj*copy=NSCopyObject(self,0,zone);
  44. copy->name=[self.namemutableCopy];
  45. copy->ageage=age;
  46. returncopy;
  47. }
  48. @end
  49. </nscopying>

小结:

对于非容器类对象,有:

如果对一个不可变对象复制,copy是指针复制,即浅拷贝;而mutableCopy则是对象复制,即深拷贝。(示例1)

如果是对可变对象复制,都是深拷贝,但copy复制返回的对象是不可变的。(示例2)


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

分享到:
评论

相关推荐

    从C++到Objective C的学习之路

    从C++过渡到Objective C的学习之旅是一条富有挑战的道路,但同时也充满了机遇。以下是一些关键的知识点,将帮助你理解这两个语言之间的异同以及如何有效地进行转换。 1. **面向对象编程基础**:C++和Objective C都...

    ObjectiveC 学习 入门基 础教程第2版

    本教程《ObjectiveC学习入门基础教程第2版》是为初学者设计的,旨在帮助新手逐步掌握ObjectiveC的基础知识和核心概念。 ObjectiveC的起源与特点: ObjectiveC是在C语言的基础上扩展的,因此它保留了C的语法结构,...

    iOS深浅拷贝例子

    在Objective-C中,实现深拷贝可以通过遵循`NSMutableCopying`协议来实现,它提供了一个`mutableCopy`方法。此方法返回一个新的可变对象,该对象是原对象的副本,并且所有嵌套的对象也都被复制。在我们的`Person`类...

    Objective c 学习方法

    ### Objective C 学习方法详解 #### 一、学习资源推荐与基础知识准备 Objective C 是一种面向对象的编程语言,广泛应用于 iOS 和 Mac OS X 的应用程序开发中。学习 Objective C 需要一定的前置知识,比如熟悉 C ...

    Objective C 串口通信源码

    总之,Objective C 串口通信源码是一个很好的学习资源,涵盖了硬件接口操作、数据传输、错误处理和多线程编程等多个核心概念。通过深入研究,开发者能够提升自己在嵌入式系统和硬件交互方面的技能。

    Objective C 2.0 官方文档

    ### Objective C 2.0 官方文档知识点详解 #### 一、Objective C 2.0 概述 Objective C 是一种面向对象的编程语言,它在标准C的基础上增加了面向对象的功能,是苹果公司用于开发iOS和macOS应用程序的主要语言之一。...

    ObjectiveC&C++的混合编译简单demo

    ObjectiveC和C++是两种...在实际项目中,可能会遇到更多挑战,比如内存管理(ObjectiveC使用ARC,而C++使用自己的内存管理机制)、异常处理(ObjectiveC不支持异常,而C++支持)等,这些都需要深入学习和实践来掌握。

    IOS深浅拷贝例子

    在iOS开发中,深拷贝和浅拷贝是Objective-C中的重要概念,主要与对象的内存管理机制有关。本文将详细解析这两个概念,并通过实际的代码示例来展示它们的区别和可能带来的意外结果。 首先,我们需要理解什么是拷贝。...

    Objective C 学习心得 (一):--Windows下搭建objective C开发环境.docx

    在本文中,我们将探讨如何在Windows环境下搭建Objective C的开发环境,这对于那些想学习Objective C但又没有Mac电脑的人来说至关重要。 首先,我们需要在GNUstep官方网站下载四个关键的软件包:GNUstep MSYS System...

    ObjectiveC基础教程

    ObjectiveC基础教程 非常不错的入门资源

    Objective C 学习笔记.pdf

    Objective C 学习笔记

    ios内存管理之深浅拷贝

    `copy`方法是Objective-C中用于执行拷贝操作的关键。对于实现了`NSCopying`协议的对象,`copy`方法会执行浅拷贝;而对于那些实现了`NSMutableCopying`协议的对象,`copy`方法通常会执行深拷贝。 `retainCount`是一...

    objective c中文版.pdf

    objective c中文版.pdf 开发ios 必备

    objective C开发经典教程

    尽管原文为英文版,但其内容详实、讲解清晰,对于希望掌握Objective C的开发者而言,是一份不可多得的学习资源。下面将对本书涉及的关键知识点进行详细阐述。 ### Objective C基础 Objective C是一种面向对象的...

    Objective C 第六版

    此外,学习 Objective-C 也有助于更好地理解 iOS 和 macOS 应用的底层机制,为开发者提供更广阔的视角。 总之,Objective-C 第六版不仅是一门强大的编程语言,也是进入 iOS 和 macOS 开发世界的钥匙。无论是对于...

    Objective C基础教程(第2版

    Objective-C中文版基础教程。Objective-C是苹果Mac OS X 上开发的首选语言,主要是因为Mac OS X 技术源自NextStep的OpenStep操作系统, 因为OPENSTEP的软件架构(framework) 都是用Objetive-C 写成,所以MacOS X上...

    Apple iphone Objective C Programming Guide

    在给定的文件信息中,我们探讨的主题是与苹果iPhone相关的...通过学习这份指南,开发者不仅可以掌握Objective-C的核心概念,还能了解到苹果生态系统中的最佳实践,从而为创建高质量的iOS应用程序奠定坚实的基础。

Global site tag (gtag.js) - Google Analytics