首页 Objective-C-2.0程序设计-第18章-复制对象

Objective-C-2.0程序设计-第18章-复制对象

举报
开通vip

Objective-C-2.0程序设计-第18章-复制对象目录18.1Copy和MutableCopy方法18.2浅复制和深复制18.3实现协议18.4用赋值方法和取值方法复制对象第一页,共22页。18.1Copy和MutableCopy方法Foudation类实现了名为copy和mutableCopy的方法,可以使用这些方法创建对象的副本,通过一个符合协议的方法来完成此任务。如果类必须区分要产生对象的是可变副本还是不可变副本,还需要根据协议实现一个方法。第二页,共22页。18.1Copy和MutableCopy方法回顾Foundation类的copy方法,给定前面描述的...

Objective-C-2.0程序设计-第18章-复制对象
目录18.1Copy和MutableCopy 方法 快递客服问题件处理详细方法山木方法pdf计算方法pdf华与华方法下载八字理论方法下载 18.2浅复制和深复制18.3实现 协议 离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载 18.4用赋值方法和取值方法复制对象第一页,共22页。18.1Copy和MutableCopy方法Foudation类实现了名为copy和mutableCopy的方法,可以使用这些方法创建对象的副本,通过一个符合协议的方法来完成此任务。如果类必须区分要产生对象的是可变副本还是不可变副本,还需要根据协议实现一个方法。第二页,共22页。18.1Copy和MutableCopy方法回顾Foundation类的copy方法,给定前面描述的两个NSMutableArray对象dataArray2和dataArray语句在内存中创建了一个新的dataArray副本,并复制了它的所有元素。随后,执行语句删除了dataArray2中的第一个元素,但却不删除dataArray中的元素。代码18-1说明了这个情况。dataArray2=[dataArraymutableCopy];[dataArray2removeObjectAtIndex:0];第三页,共22页。Program18.1#import#import#import#importintmain(intargc,char*argv[]){NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];NSMutableArray*dataArray=[NSMutableArrayarrayWithObjects:@”one”,@”two”,@”three”,@”four”,nil];NSMutableArray*dataArray2;//simpleassignmentdataArray2=dataArray;[dataArray2removeObjectAtIndex:0];NSLog(@”dataArray:“);for(NSString*elemindataArray)NSLog(@”%@”,elem);NSLog(@”dataArray2:“);for(NSString*elemindataArray2)NSLog(@”%@”,elem);//tryaCopy,thenremovethefirstelementfromthecopy*第四页,共22页。dataArray2=[dataArraymutableCopy];[dataArray2removeObjectAtIndex:0];NSLog(@”dataArray:“);for(NSString*elemindataArray)NSLog(@”%@”,elem);NSLog(@”dataArray2:“);for(NSString*elemindataArray2)NSLog(@”%@”,elem);[dataArray2release];[pooldrain];return0;}Program18.1OutputdataArray:twothreefourdataArray2:twothreefourdataArray:twothreefourdataArray2:threefour*第五页,共22页。该程序定义了可变数组对象dataArray,并分别将其元素设置为字符串对象@”one”、@”two”@”three”@”four”。前面讨论过,赋值语句dataArray2=dataArray;仅仅创建了对内存中同一个数组对象的另一个引用。从dataArray2中删除第一个对象并随后输出两个数组对象中的元素。不出意料,这两个引用中的第一个元素(字符串@”one”)都会消失。接下来,创建一个dataArray的可变副本并将它赋值给dataArray2的最终副本。这样在内存中创建了两个截然不同的可变数组,两者都包含三个元素。现在,删除dataArray2中的第一个元素,不会对dataArray的内容有任何影响,正如程序输出的最后两行验证一样。*第六页,共22页。18.1Copy和MutableCopy方法注意,产生一个对象的可变副本并不要求被复制的对象本身是可变的。这种情况同样适用于不可变副本:可以创建可变对象的不可变副本。还要注意在产生数组的副本时,数组中每个元素的保持计数将通过复制操作自动增1。因此,如果产生数组的副本并随即释放原始数组,那么副本仍然包含有效的元素。因为dataArray的副本是在程序中使用mutableCopy方法产生的,所以要负责释放它的内存。上一章讲述了释放自己使用的一个copy方法创建的对象这条规则。这解释了下面这个程序行[dataArray2release];的实质。第七页,共22页。18.2浅复制与深复制代码清单18-1使用不可变字符串来填充dataArray的元素(常量字符串对象是不可变的)。代码清单18-2中,将使用可变字符串代替它来填充数组,这样就可以改变数组中的一个字符串。Program18.2#import#import#import#importintmain(intargc,char*argv[]){NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];NSMutableArray*dataArray=[NSMutableArrayarrayWithObjects:[NSMutableStringstringWithString:@”one”],[NSMutableStringstringWithString:@”two”],[NSMutableStringstringWithString:@”three”],nil];NSMutableArray*dataArray2;NSMutableString*mStr;NSLog(@”dataArray:“);for(NSString*elemindataArray)*第八页,共22页。//makeacopy,thenchangeoneofthestringsdataArray2=[dataArraymutableCopy];mStr=[dataArrayobjectAtIndex:0];[mStrappendString:@”ONE”];NSLog(@”dataArray:“);for(NSString*elemindataArray)NSLog(@”%@”,elem);NSLog(@”dataArray2:“);for(NSString*elemindataArray2)NSLog(@”%@”,elem);[dataArray2release];[pooldrain];return0;}Program18.2OutputdataArray:onetwothreedataArray:oneONEtwothreedataArray2:oneONEtwothree*第九页,共22页。18.2浅复制与深复制使用下面的语句检索dataArray的第一个元素:mStr=[dataArrayobjectAtIndex:0];然后,使用下面的语句将字符串@”ONE”附加到这个元素:[mStrappendString:@”ONE”];注意,原始数组及其副本中的第一个元素的值:它们都修改了。从集合中获取元素时,就得到了这个元素的一个新引用,但并不是一个新副本。所以,对dataArray调用objectAtIndex:方法时,返回的对象与dataArray中的第一个元素都指向内存中的同一个对象。随后,修改string对象mStr的副作用就是同时改变了dataArray的第一个元素。副本的第一个元素被改变的原因是默认的浅复制方式。它意味着使用mutableCopy方法复制数组时,在内存中为新的数组对象分配了空间,并且将单个元素复制到新数组中。然而将原始素组中的每个元素复制到新位置意味着:仅将引用从一个数组元素复制到另一个数组元素。这样做的最终结果,就是这两个数组中的元素都指向内存中的一个字符串。*第十页,共22页。18.2浅复制与深复制要为数组中每个元素创建完全不同的副本,需要执行所谓的深复制。这就意味着要创建数组中的每个对象内容的副本,而不仅是这些对象的引用的副本(并且考虑一下,如果一个数组中的元素本身是数组对象时,深复制意味着该如何处理)。然而使用Foundation类的copy或mutableCopy方法时,深复制并不是默认执行的。第十一页,共22页。18.3实现协议如果尝试使用自己类(例如地址薄)中的copy方法,如下所示:NewBook=[myBookmutableCopy];将会收到如下错误信息:***-[AddressBookcopyWithZone:]:selectornotrecognized***Uncaughtexception:***-[AddressBookcopyWithZone:]:selectornotrecognized正如提示,要实现使用自己的类进行复制,必须根据协议实现其中一两个方法。我们将展示如何为Fraction类添加copy方法,注意,这里描述的复制策略的技巧非常适合用于你自己的类。如果这些类是Foundation类的子类,可能需要较复杂的复制策略:超类可能已经实现了它自己的复制策略。要产生Fraction类的一个对象的副本,需要分配一个新分数空间并简单将这两个整数复制到新分数中。*第十二页,共22页。18.3实现协议实现协议时,类必须实现copyWithZone:方法来响应copy消息。(这条copy消息仅将一条带有nil参数的copyWithZone:消息发送给你的类)。注意,如果想要区分可变副本和不可变副本,还需要根据协议实现mutableCopyWithZone:方法。如果两个方法都实现,那么copyWithZone:应该返回不可变副本,而mutableCopytWithZone:将返回可变副本。产生对象的可变副本并不要求被复制的对象本身也是可变的(反之亦然);想要产生不可变对象的可变副本是很合理的(例如,考虑字符串对象)。@interface指令应该如下所示:@interfaceFraction:NSObjectFraction是NSObject的子类,并且符合NSCopying协议。第十三页,共22页。在实现文件Fraction.m中,为新方法添加下列定义:-(id)copyWithZone:(NSZone*)zone{Fraction*newFract=[[FractionallocWithZone:zone]init];[newFractsetTo:numeratorover:denominator];returnnewFract;}参数zone与不同的存储区有关,你可以在程序中分配并使用这些存储区。只有在编写要分配大量内存的应用程序并且想要通过将空间分配分组到这些存储区中来优化内存分配时,才需处理这些zone。可以使用传递给copyWithZone:的值,并将它传给名为allocWithZone:的内存分配方法。这个方法在制定存储区中分配内存。分配新的Fraction对象后,将接受者的numerator和denominator变量复制到其中。copyWithZone:方法应该返回对象的新副本,这个对象就是在你的方法中实现的。代码18-3测试了你的新方法。*第十四页,共22页。Program18.3//Copyingfractions#import“Fraction.h”#importintmain(intargc,char*argv[]){NSAutoreleasePool*pool=[[NSAutoreleasePoolalloc]init];Fraction*f1=[[Fractionalloc]init];Fraction*f2;[f1setTo:2over:5];f2=[f1copy];[f2setTo:1over:3];[f1print];[f2print];[f1release];[f2release];[pooldrain];return0;}Program18.3Output2/51/3*第十五页,共22页。该程序调用copy方法来产生副本,copy方法向你的对象发送copyWithZone:消息。这个方法产生了一个新Fraction,将f1的值复制到其中,并返回结果。返回main中,将该结果赋给f2。随后,将f2的值置为1/3.将f2=[f1copy];改为:f2=f1;并在程序结尾删除f2的release语句,可以获得不同结果。如果你的类可以产生子类,那个copyWithZone:方法将被继承。那么,该方法中的程序行Fraction*newFract=[[FractionallocWithZone:zone]init];需要改成Fraction*newFract=[[[selfclass]allocWithZone:zone]init];这样,可以从该类分配一个新对象,而这个类是copy的接受者(例如,它产生了一个NewFraction的子类,那么应该确保在继承的方法中分配了新的NewFraction对象,而不是Fraction对象)。如果编写一个类的copyWithZone:方法,而该类的超累也实现了协议,那么先调用超类的copy方法来复制继承来的实例变量,然后假如自己的代码以复制想要添加到该类中的任何实例变量。*第十六页,共22页。18.4用赋值方法和取值方法复制对象只要实现赋值方法或取值方法,都应该考虑实例变量中存储的内容、要检索的内容以及是否需要保护这些值。例如,考虑使用setName:方法来设置AddressCard对象的名称时:[newCardsetName:newName];假设newName是一个字符串对象,它包含新地址卡片的名称。假定在赋值方法例程内,你只是简单地将参数赋值给相应的实例变量:-(void)setName:(NSString*)theName{name=theName;}第十七页,共22页。18.4用赋值方法和取值方法复制对象现在,如果随后更改了程序的newName中包含的一些字符,那么你认为会发生什么?对,这样也会无意间改变地址卡片中对应的域,因为它们都引用相同的string对象。前面已经学过,为了避免无意间对程序产生影响,比较安全的途径是在赋值方法例程中产生对象的副本,通过使用alloc方法来创建新的string对象,然后使用initWithString函数将该方法提供的参数值赋给它,可以实现在赋值对象中产生副本。第十八页,共22页。18.4用赋值方法和取值方法复制对象还可以编写如下的setName:方法来使用copy:当然,要使赋值方法例程的内存管理友好一些,首先应该自动释放旧的值,如下所示:-(void)setName:(NSString*)theName{name=[theNamecopy];}-(void)setName:(NSString*)theName{[nameautorelease];name=[theNamecopy];}第十九页,共22页。18.4用赋值方法和取值方法复制对象如果在属性声明中为实例变量指定了copy属性,那么合并后的方法会使用类的copy方法(你编写的copy方法或继承的copy方法)。所以下列property声明@property(nonatomic,copy)NSString*name;会生成一个合并的方法,其行为类似于-(void)setName:(NSString*)theName{if(theName!=name){[namerelease]name=[theNamecopy];}}第二十页,共22页。18.4用赋值方法和取值方法复制对象此处使用nonatomic是为了告诉系统不要使用mutex(互斥)锁定保护属性存取器方法。如果未指定nonatomic或者指定了atomic(这是默认值),那么会使用mutex锁定保护实例变量。另外,合并的取值方法将被保持,并在实例变量的值返回前自动释放该实例变量。关于保护实例变量值的讨论同样适用于取值例程。如果返回对象,那么必须确保对返回值的改变不影响你的实例变量的值。在这样的情况下,可以生成实例变量的副本,并将它用作返回值。第二十一页,共22页。回到copy方法的实现,如果正在复制的实例变量包含不可变的对象,那么可能不需要生成这个对象内容的副本。仅通过保持该对象来生成它的新引用就足够了。例如,为AddreCard类实现copy方法时,这个类包含name和email对象,下面实现的copyWithZone:方法就够了。-(AddresssCard*)copyWithZone:(NSZone*)zone{AddressCard*newCard=[[AddressCardallocWithZone:zone]init];[newCardretainName:nameandEmail:email];returnnewCard;}-(void)retainName:(NSString*)theNameandEmail:(NSString*)theEmail{name=[theNameretain];email=[theEmailretain];}这里没有使用setName:andEmail:方法来复制实例变量,因为这个方法生成了它的参数的新副本。可以替换为retainName:andEmail:的新方法保持两个变量。*第二十二页,共22页。
本文档为【Objective-C-2.0程序设计-第18章-复制对象】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_997338
暂无简介~
格式:ppt
大小:413KB
软件:PowerPoint
页数:22
分类:工学
上传时间:2018-09-18
浏览量:1