在ObjectiveC 中,什么是深浅拷贝?深浅拷贝分别指深拷贝和浅拷贝,即mutableCopy和copy方法。
copy复制一个不可变对象,而mutableCopy复制一个mutable可变对象。
什么时候用到深浅拷贝?下面举几个例子说明。非容器类对象如NSString,NSNumber等一类对象
示例1:
- //非容器类对象NSString*str=@"originstring";
-
NSString*strCopy=[strcopy];
-
NSMutableString*mstrCopy=[strmutableCopy];
- [mstrCopyappendString:@"??"];
查看内存可以发现,str和strCopy指向的是同一块内存区域,我们称之为弱引用(weak reference)。而mstrCopy是真正的复制,系统为其分配了新内存空间,保存从str复制过来的字符串值。从最后一行代码中修改这些值而不影响str和strCopy中可证明。
示例2:
- NSMutableString*mstr=[NSMutableStringstringWithString:@"origin"];
-
NSString*strCopy=[mstrcopy];
-
NSMutableString*mstrCopy=[mstrcopy];
-
NSMutableString*mstrMCopy=[mstrmutableCopy];
- //[mstrCopyappendString:@"1111"];//error
- [mstrappendString:@"222"];
- [mstrMCopyappendString:@"333"];
以上四个对象所分配的内存都是不一样的。而且对于mstrCopy,它所指向的其实是一个imutable对象,是不可改变的,所以会出错。这点要注意,好好理解。
容器类对象深浅复制
比如NSArray,NSDictionary等。对于容器类本身,上面讨论的结论也适用的,下面探讨的是复制后容器内对象的变化。
示例3
- /*copy返回不可变对象,mutablecopy返回可变对象*/
-
-
NSArray*array1=[NSArrayarrayWithObjects:@"a",@"b",@"c",nil];
-
NSArray*arrayCopy1=[array1copy];
- //arrayCopy1是和array同一个NSArray对象(指向相同的对象),包括array里面的元素也是指向相同的指针
- NSLog(@"array1retaincount:%d",[array1retainCount]);
- NSLog(@"array1retaincount:%d",[arrayCopy1retainCount]);
-
-
NSMutableArray*mArrayCopy1=[array1mutableCopy];
- //mArrayCopy1是array1的可变副本,指向的对象和array1不同,但是其中的元素和array1中的元素指向的还是同一个对象。mArrayCopy1还可以修改自己的对象
- [mArrayCopy1addObject:@"de"];
- [mArrayCopy1removeObjectAtIndex:0];
array1和arrayCopy1是指针复制,而mArrayCopy1是对象复制,符合前面示例1讨论的结论。mArrayCopy1可以改变其内的元素:删除或添加。但容器内的元素内容都是浅拷贝。
示例4
- NSArray*mArray1=[NSArrayarrayWithObjects:[NSMutableStringstringWithString:@"a"],@"b",@"c",nil];
- NSLog(@"mArray1retaincount:%d",[mArray1retainCount]);
-
NSArray*mArrayCopy2=[mArray1copy];
- NSLog(@"mArray1retaincount:%d",[mArray1retainCount]);
- //mArray1和mArrayCopy2指向同一对象,retain值+1。
-
-
NSMutableArray*mArrayMCopy1=[mArray1mutableCopy];
- NSLog(@"mArray1retaincount:%d",[mArray1retainCount]);//mArrayCopy2和mArray1指向的是不一样的对象,但是其中的元素都是一样的对象——同一个指针
-
NSMutableString*testString=[mArray1objectAtIndex:0];
-
//testString=@"1a1";//这样会改变testString的指针,其实是将@“1a1”临时对象赋给了testString
- [testStringappendString:@"tail"];//这样以上三个数组的首元素都被改变了
由此可见,对于容器而言,其元素对象始终是指针复制。如果需要元素对象也是对象复制,就需要实现深拷贝。http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Collections/Articles/Copying.html
示例5
- NSArray*array=[NSArrayarrayWithObjects:[NSMutableStringstringWithString:@"first"],[NSStringstringWithString:@"b"],@"c",nil];
-
NSArray*deepCopyArray=[[NSArrayalloc]initWithArray:arraycopyItems:YES];
-
NSArray*trueDeepCopyArray=[NSKeyedUnarchiverunarchiveObjectWithData:
- [NSKeyedArchiverarchivedDataWithRootObject:array]];
trueDeepCopyArray是完全意义上的深拷贝,而deepCopyArray则不是,对于deepCopyArray内的不可变元素其还是指针复制。
或者我们自己实现深拷贝的方法。因为如果容器的某一元素是不可变的,那你复制完后该对象仍旧是不能改变的,因此只需要指针复制即可。除非你对容器内的元素重新赋值,否则指针复制即已足够。
举个例子,[[array objectAtIndex:0]appendstring:@”sd”]后其他的容器内对象并不会受影响。[[array objectAtIndex:1]和[[deepCopyArray
objectAtIndex:0]尽管是指向同一块内存,但是我们没有办法对其进行修改——因为它是不可改变的。所以指针复制已经足够。所以这并不是完全意义上的深拷贝。
自己实现深拷贝的方法
NSDictionaryMutableDeepCopy.h
- 8#import<foundation/Foundation.h>
- @interfaceNSDictionary(MutableDeepCopy)
- -(NSMutableDictionary*)mutableDeepCopy;
- @end
-
</foundation>
- NSDictionaryMutableDeepCopy.m
- #import"NSDictionaryMutableDeepCopy.h"
- @implementationNSDictionary(MutableDeepCopy)
- -(NSMutableDictionary*)mutableDeepCopy{
-
NSMutableDictionary*ret=[[NSMutableDictionaryalloc]
- initWithCapacity:[selfcount]];
-
NSArray*keys=[selfallKeys];
- for(idkeyinkeys){
-
idoneValue=[selfvalueForKey:key];
-
idoneCopy=nil;
- if([oneValuerespondsToSelector:@selector(mutableDeepCopy)]){
-
oneCopy=[oneValuemutableDeepCopy];
- }
- elseif([oneValuerespondsToSelector:@selector(mutableCopy)]){
-
oneCopy=[oneValuemutableCopy];
- }
-
if(oneCopy==nil){
-
oneCopy=[oneValuecopy];
- }
- [retsetValue:oneCopyforKey:key];
- }
- returnret;
- }
- @end
使用类别方法来实现。
自定义对象
如果是我们定义的对象,那么我们自己要实现NSCopying,NSMutableCopying这样就能调用copy和mutablecopy了。举个例子:
- @interfaceMyObj:NSObject<nscopying,NSMutableCopying>
- {
- NSMutableString*name;
- NSString*imutableStr;
- intage;
- }
- @property(nonatomic,retain)NSMutableString*name;
- @property(nonatomic,retain)NSString*imutableStr;
- @property(nonatomic)intage;
-
- @end
- @implementationMyObj
- @synthesizename;
- @synthesizeage;
- @synthesizeimutableStr;
- -(id)init
- {
-
if(self=[superinit])
- {
-
self.name=[[NSMutableStringalloc]init];
-
self.imutableStr=[[NSStringalloc]init];
-
age=-1;
- }
- returnself;
- }
- -(void)dealloc
- {
- [namerelease];
- [imutableStrrelease];
- [superdealloc];
- }
- -(id)copyWithZone:(NSZone*)zone
- {
-
MyObj*copy=[[[selfclass]allocWithZone:zone]init];
-
copy->name=[namecopy];
-
copy->imutableStr=[imutableStrcopy];
-
//copy->name=[namecopyWithZone:zone];;
-
//copy->imutableStr=[namecopyWithZone:zone];//
-
copy->ageage=age;
-
- returncopy;
- }
- -(id)mutableCopyWithZone:(NSZone*)zone
- {
-
MyObj*copy=NSCopyObject(self,0,zone);
-
copy->name=[self.namemutableCopy];
-
copy->ageage=age;
- returncopy;
- }
- @end
-
</nscopying>
小结:
对于非容器类对象,有:
如果对一个不可变对象复制,copy是指针复制,即浅拷贝;而mutableCopy则是对象复制,即深拷贝。(示例1)
如果是对可变对象复制,都是深拷贝,但copy复制返回的对象是不可变的。(示例2)
转载自:http://mobile.51cto.com/iphone-267060.htm
分享到:
相关推荐
从C++过渡到Objective C的学习之旅是一条富有挑战的道路,但同时也充满了机遇。以下是一些关键的知识点,将帮助你理解这两个语言之间的异同以及如何有效地进行转换。 1. **面向对象编程基础**:C++和Objective C都...
本教程《ObjectiveC学习入门基础教程第2版》是为初学者设计的,旨在帮助新手逐步掌握ObjectiveC的基础知识和核心概念。 ObjectiveC的起源与特点: ObjectiveC是在C语言的基础上扩展的,因此它保留了C的语法结构,...
在Objective-C中,实现深拷贝可以通过遵循`NSMutableCopying`协议来实现,它提供了一个`mutableCopy`方法。此方法返回一个新的可变对象,该对象是原对象的副本,并且所有嵌套的对象也都被复制。在我们的`Person`类...
### Objective C 学习方法详解 #### 一、学习资源推荐与基础知识准备 Objective C 是一种面向对象的编程语言,广泛应用于 iOS 和 Mac OS X 的应用程序开发中。学习 Objective C 需要一定的前置知识,比如熟悉 C ...
总之,Objective C 串口通信源码是一个很好的学习资源,涵盖了硬件接口操作、数据传输、错误处理和多线程编程等多个核心概念。通过深入研究,开发者能够提升自己在嵌入式系统和硬件交互方面的技能。
### Objective C 2.0 官方文档知识点详解 #### 一、Objective C 2.0 概述 Objective C 是一种面向对象的编程语言,它在标准C的基础上增加了面向对象的功能,是苹果公司用于开发iOS和macOS应用程序的主要语言之一。...
ObjectiveC和C++是两种...在实际项目中,可能会遇到更多挑战,比如内存管理(ObjectiveC使用ARC,而C++使用自己的内存管理机制)、异常处理(ObjectiveC不支持异常,而C++支持)等,这些都需要深入学习和实践来掌握。
在iOS开发中,深拷贝和浅拷贝是Objective-C中的重要概念,主要与对象的内存管理机制有关。本文将详细解析这两个概念,并通过实际的代码示例来展示它们的区别和可能带来的意外结果。 首先,我们需要理解什么是拷贝。...
在本文中,我们将探讨如何在Windows环境下搭建Objective C的开发环境,这对于那些想学习Objective C但又没有Mac电脑的人来说至关重要。 首先,我们需要在GNUstep官方网站下载四个关键的软件包:GNUstep MSYS System...
ObjectiveC基础教程 非常不错的入门资源
Objective C 学习笔记
`copy`方法是Objective-C中用于执行拷贝操作的关键。对于实现了`NSCopying`协议的对象,`copy`方法会执行浅拷贝;而对于那些实现了`NSMutableCopying`协议的对象,`copy`方法通常会执行深拷贝。 `retainCount`是一...
objective c中文版.pdf 开发ios 必备
尽管原文为英文版,但其内容详实、讲解清晰,对于希望掌握Objective C的开发者而言,是一份不可多得的学习资源。下面将对本书涉及的关键知识点进行详细阐述。 ### Objective C基础 Objective C是一种面向对象的...
此外,学习 Objective-C 也有助于更好地理解 iOS 和 macOS 应用的底层机制,为开发者提供更广阔的视角。 总之,Objective-C 第六版不仅是一门强大的编程语言,也是进入 iOS 和 macOS 开发世界的钥匙。无论是对于...
Objective-C中文版基础教程。Objective-C是苹果Mac OS X 上开发的首选语言,主要是因为Mac OS X 技术源自NextStep的OpenStep操作系统, 因为OPENSTEP的软件架构(framework) 都是用Objetive-C 写成,所以MacOS X上...
在给定的文件信息中,我们探讨的主题是与苹果iPhone相关的...通过学习这份指南,开发者不仅可以掌握Objective-C的核心概念,还能了解到苹果生态系统中的最佳实践,从而为创建高质量的iOS应用程序奠定坚实的基础。