1 // 2 // main.m 3 // cope-MultableCopy 4 // 5 // Created by dingxiaowei on 13-5-19. 6 // Copyright (c) 2013年 dingxiaowei. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 #import "Student.h" 11 #import "GoodStudent.h" 12 //copy语法的目的:改变副本的时候,不会影响到原对像 13 14 //只有一种情况是浅拷贝,不可变对象调用copy方法,才是浅拷贝 15 16 #pragma mark - 演示字符串的mutableCopy语法(深拷贝) 17 //深拷贝:是内容拷贝,会产生新对象,新对象计数器加1,原对象不变 18 void stringmutableCopy(){ 19 20 NSString *str=[[NSString alloc] initWithFormat:@"hello,%i。",10]; 21 NSLog(@"%@",str); 22 //复制一个对象 23 //产生一个新对象,计数器为1,原对象计数器不变 24 NSMutableString *mustr=[str mutableCopy]; 25 NSLog(@"str:%zi",[str retainCount]); 26 NSLog(@"mustr:%zi",[mustr retainCount]); 27 28 //判断是否是不同对象,str与mustr不是相同对象 29 NSLog(@"%i",str==mustr); 30 31 //拼接一个字符串 32 [mustr appendString:@"I am dingxiaowei"]; 33 NSLog(@"原来str%@",str); 34 NSLog(@"现在mustr%@",mustr); 35 36 [mustr release]; 37 [str release]; 38 } 39 #pragma mark - 演示字符串的Copy语法(浅拷贝) 40 //浅拷贝:是地址拷贝,不会产生新对象,原对象计数器加1 41 void stringCopy(){ 42 NSString *str=[[NSString alloc] initWithFormat:@"hi%i",10]; 43 NSLog(@"str:%zi",[str retainCount]); 44 //copy产生的是不可变副本,由于原对像本来就不可变,所以为了性能着想,copy直接返回原对像本身 45 NSString *newstr=[str copy]; 46 NSLog(@"str:%zi",[str retainCount]); //由于是同一个对象,所以相当于str进行了一次retain操作 47 NSLog(@"newstr:%zi",[newstr retainCount]); 48 //返回值为1,说明还是返回的原来的对象,相当于return操作 49 NSLog(@"是否相同:%i",str==newstr); 50 51 //执行两次release之后,才能完全释放该对象 52 [str release]; 53 [newstr release]; 54 //NSLog(@"%zi",[str retainCount]); 55 } 56 #pragma mark - 可变字符串的copy(深拷贝) 57 void mutableStringCopy(){ 58 NSMutableString *string=[NSMutableString stringWithFormat:@"age is %i",10]; 59 //会产生一个新对象,计数器加1 60 NSString *str=[string copy]; 61 //判断是否是同一个对象 62 NSLog(@"%i",string==str); 63 64 65 [str release]; 66 // NSLog(@"%zi",[str retainCount]); 67 } 68 #pragma mark - 可变字符串的mutableCopy方法(深拷贝) 69 void mutableStringmutableCopy(){ 70 NSMutableString *string=[NSMutableString stringWithFormat:@"age is %i",10]; 71 72 //产生一个新的对象,计数器加1 73 NSMutableString *str=[string mutableCopy]; 74 [str appendString:@" 附加的字符串"]; 75 NSLog(@"%@",str); 76 NSLog(@"%@",string); 77 [str release]; 78 } 79 #pragma mark - 演示Student的name的copy方法 80 void studentNameCopy(){ 81 Student *stu=[[[Student alloc] init] autorelease]; 82 NSMutableString *string=[NSMutableString stringWithFormat:@"age is %i",10]; 83 stu.name=string; 84 [string appendString:@" append string"]; 85 //如果前面写的是Property(retain)NSString*name,那么这两句打印的结果就是一样的 都附加了string 86 NSLog(@"name=%@",stu.name); 87 //拷贝名字给副本对象 88 Student *stucopy=[stu copy]; 89 90 //打印两个对象 91 NSLog(@"Stu1:%@",stu); 92 NSLog(@"Stu2:%@",stucopy); 93 94 //因为内部实现的时候没有release,所以这里要必须释放对象 95 [stucopy release]; 96 97 } 98 #pragma mark - 演示StudentCopy方法 99 void studentCopy(){ 100 Student *stu=[Student studentWithName:@"stu1"]; 101 Student *stu2=[stu copy]; 102 103 NSLog(@"stu1:%@",stu); 104 NSLog(@"修改前stu2:%@",stu2); 105 stu2.name=@"stu2"; 106 NSLog(@"修改后stu2:%@",stu2); 107 108 [stu2 release]; 109 } 110 #pragma mark - goodstudent的copy演示 111 void goodstudentCopy(){ 112 GoodStudent *goodstudent=[GoodStudent goodstudentWithAge:20 Name:@"dingxiaowei"]; //这里要注意:调用的父类初始化方法,要在父类初始化方法里写一个【self class】alloc来创建一个初始化对象,返回一个子类的对象 113 NSLog(@"%@",goodstudent); 114 GoodStudent *newgoodstudent=[goodstudent copy]; //注意:这儿调用copy方法的时候,会取调用ocopywithzone方法,由于GoodStudent中没有实现,所以会取调用父类的这个方法,返回又会是父类对象,所以这里要注意修改父类方法里面那个方法的初始化对象,改成【self class】,或者对这个方法子类进行重写 115 NSLog(@"stu1:%@",goodstudent); 116 NSLog(@"修改前的stu2:%@",newgoodstudent); //发现成功拷贝了 117 118 //修改stu2信息 119 newgoodstudent.name=@"cl"; 120 newgoodstudent.age=22; 121 NSLog(@"修改后的stu2:%@",newgoodstudent); 122 } 123 int main(int argc, const char * argv[]) 124 { 125 126 @autoreleasepool { 127 128 // stringmutableCopy(); 129 // stringCopy(); 130 // mutableStringCopy(); 131 // mutableStringmutableCopy(); 132 // studentNameCopy(); 133 // studentCopy(); 134 goodstudentCopy(); 135 } 136 return 0; 137 }
Student.h
1 #import <Foundation/Foundation.h> 2 3 @interface Student : NSObject<NSCopying> //要实现NSCopying协议,才能调用类的copy方法 4 //copy代表set方法会先release旧对象,然后copy新对象 5 //用copy的话,修改外部的变量就不会印象到内部的成员变量 6 //建议:一般NSString用copy,其他对象用retain策略 7 //@property(nonatomic,copy)NSString *name; 8 @property(nonatomic,retain)NSString *name; 9 10 -(id)copyWithZone:(NSZone *)zone; 11 12 +(id)studentWithName:(NSString *)name; 13 @end
Student.m
1 #import "Student.h" 2 3 @implementation Student 4 5 //-(void)setName:(NSString *)name{ 6 // if(_name!=name){ 7 // [_name release]; 8 // //_name=[name retain]; //如果前面是Property(nonautomic,retain)所做的事情 9 // //如果前面是Property(nonautomic,copy) 10 // _name=[name copy]; 11 // } 12 //} 13 14 +(id)studentWithName:(NSString *)name{ 15 Student *stu=[[[[self class] alloc] init] autorelease]; //注意,这里[self class]取代Student 就是为了防止如果子类调用父类的方法,则返回的是父类的对象,会产生错误,所以这么操作就是返回子类的对象 16 stu.name=name; 17 return stu; 18 } 19 -(NSString *)description{ 20 return [NSString stringWithFormat:@"[name=%@]",_name]; 21 } 22 23 #pragma mark - copying方法 24 -(id)copyWithZone:(NSZone *)zone{ 25 //注意:这里创建的copy对象,不要释放对象,因为我们在外面调用copy方法然后释放对象,在这里就不需要释放了 26 Student *copy=[[[self class] allocWithZone:zone] init]; //这里要特别注意:防止子类直接调用这个copywithzone方法而返回的是父类对象,要改成【self class】 27 copy.name=self.name; 28 return copy; 29 } 30 31 -(void)dealloc{ 32 [_name release]; 33 [super release]; 34 } 35 @end
GoodStudent.h
1 #import "Student.h" 2 3 @interface GoodStudent : Student 4 //assign帮我们自动生成set和get方法 5 @property(nonatomic,assign) int age; 6 7 //-(void)setAge:(int)age; 8 //-(int)age; 9 10 +(id)goodstudentWithAge:(int) age Name:(NSString *)name; 11 @end
GoodStudent.m
1 #import "GoodStudent.h" 2 3 @implementation GoodStudent 4 5 //-(void)setAge:(int)age{ 6 // _age=age; 7 //} 8 //-(int)age{ 9 // return _age; 10 //} 11 12 +(id)goodstudentWithAge:(int)age Name:(NSString *)name{ 13 GoodStudent *goodstudent=[GoodStudent studentWithName:name]; //这个要注意可能返回的是父类对象,要在父类中修改 14 goodstudent.age=age; 15 return goodstudent; 16 } 17 //特别注意,description方法里面不能打印self本对象,不然会出现死循环 18 -(NSString *)description{ 19 return [NSString stringWithFormat:@"goodStudent age is %i and name is %@",self.age,self.name]; 20 } 21 22 //由于父类的copywithzone方法只实现了name的copy而没有实现子类特有属性的copy,所以要重写那个copywithzone方法 23 -(id)copyWithZone:(NSZone *)zone{ 24 //首先要调用父类的这个方法 25 GoodStudent *copygoodstu=[super copyWithZone:zone]; 26 copygoodstu.age=self.age; 27 return copygoodstu; 28 } 29 30 @end
本文转自蓬莱仙羽51CTO博客,原文链接:http://blog.51cto.com/dingxiaowei/1366491,如需转载请自行联系原作者