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