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 
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 
2 3 @interface Student : NSObject
//要实现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