copy 和 mutableCopyapp
一個對象使用copy或者mutableCopy方法能夠建立對象的副本性能
---------------atom
copy - 須要先實現NSCopying協議,建立的是不可變副本(如NSString,NSArray,NSDictionary)spa
---------------3d
mutableCopy - 須要先實現NSMutableCopying協議,建立的是可變副本(如NSMutableString,NSMutableArray,NSMutableDictionary,默認都已經實現)指針
像本身建立 的 Person Student 是不能夠拷貝的,由於沒有實現這兩個協議中的一個。orm
---------------對象
深拷貝:內容拷貝,源對象和副本指向的是不一樣的兩個對象,源對象引用計數器不變,副本計數器設置爲1。內容拷貝。區別:有沒有產生新對象。blog
---------------ip
淺拷貝:指針拷貝,源對象和副本指向的是同一個對象。對象的引用計數器+1,其實至關於作了一次retain操做。地址拷貝。
---------------
只有不可變對象建立的不可變副本(copy)纔是淺複製,其餘的都是深複製。
OC中copy語法存在的意義就是改變副本不影響源對象。
因此只跟調用的方法名有關係,跟源對象不要緊。
內存管理回顧
#pragma mark mutablecopy
void stringMutablecopy(){
//string counter 1
NSString *string=[[NSString alloc] initWithFromat:@」age is %1」,10];
//str counter 1,string counter 1
// Create a new Object it’s counter is 1,source object counter is 1
NSMutableString *str=[string mutableCopy];
NSLog(@」str=%zi」,[str retainCount]); //1
NSLog(@」string=%zi」,[string retainCount]);//1
//so copy release
//not the same Object
NSLog(@」%i」,str==string);//0
//Modify str to check whether string change
[str appendString:@」abcd」];
NSLog(@」string:%@」,string);
NSLog(@」str:%@」,str);
[str release];//str:0
//string counter 0
[string release];
}
#pragma mark copy
void(){
NSString *string=[[NSString alloc] initWithFromat:@」age is %1」,10];
NSLog(@」%zi」,[string retainCount]);
NSString *str=[string copy];// Both can’t change
//淺拷貝 至關於retain ,由於str不可變,爲了性能着想,因此返回源對象自己,計數器+1
NSLog(@」%i」,str==string);//1
NSLog(@」%zi」,[string retainCount]);
[str release];
[string release];
}
//結論不管是copy 仍是 mutableCopy 都須要release
#praga mark mutable->copy 可變字符串的拷貝
void mutableStringCopy(){
NSMutableString * string=[NSMutableString stringWithFormat:@」age is %i」,10];
NString *str=[string copy];// 深拷貝
NSLog(@「%i」,str==string);
[str release];
}
void mutableStringMutableCopy(){
//確定是深拷貝
NSMutableString * string=[NSMutableString stringWithFormat:@」age is %i」,10];
NSMutableString * str=[string mutableCopy];
[str appendString:@」1234」];
NSLog(@」str:%@」,str);
NSLog(@」string:%@」,string);
[str release];
}
本身建立的類來拷貝
Student.h
//@property (nonatomic ,retain) NSString *name;
Student.m
//retain表明set方法會release舊對象,retain新對象
-(void)setName:(NSString *)name{
if(_name!=name){
[_name release];
_name=[name retain];
}
}
-(void)dealloc{
[_name release];
[super dealloc];
}
Student.h
//修改外部的變量並不會影響到內部成員
@property (nonatomic ,copy) NSString *name;
Student.m
//copy表明set方法會release舊對象,copy新對象
-(void)setName:(NSString *)name{
if(_name!=name){
[_name release];
_name=[name copy];
}
}
-(void)dealloc{
[_name release];
[super dealloc];
}
//pragma mark show copy name of Student (前面的懂,這就模糊了)
#import 「Student.h」
void studentNameCopy(){
Student *stu=[[[Student alloc] init]autorelease];
NSMutableString *string=[NSMutableString stringWithFormat:@」age is %i」,10];
stu.name=string;
[string appendString;@「123」];
NSLog(@」name=%@」,stu.name);//10
NSLog(@」string=%@」,string);//10123
}
//字符串建議通常用copy,其餘對象通常用retain
#pragma mark copy Student copy
Student.h
@interface Student:NSObject<NSCopying>
@property (nonatomic,copy) NSString *name;
+(id)studentWithName:(NSString *)name;
@end
Student.m
@implementation Student
+(id)studentWithName:(NSString *)name{
//Student *stu=[[[Studeent alloc]init]autorelease];
Student *stu=[[[[self class]alloc]init]autorelease];
//self 指向方法調用者
stu.name=name;
return stu;
}
-(void)dealloc{
[_name release];
[super dealloc];
}
//description 你能打印 self 會死循環的
-(NSString *)description{
return [NSString stringWithFormat:@「[name=%@]」,_name];
//後面GoodStudent須要
}
#pagma mark method in copying protocol zone 指向新的存儲空間
-(id)copyWithZone:(NSZone *)zone{
Student *copy=[[[self class]allocWithZone:zone]init];//此處不要求釋放
copy.name=self.name;//拷貝名字給副本對象
return copy;//誰調用誰釋放,交給外界釋放
}
@end
void student Copy(){
Student stu1=[Student studentWithName:@」stu1」];
Student stu2=[stu1 copy];
//print stu1 & stu2
NSLog(@」stu1:%@」,stu1);//stu1
NSLog(@」stu2:%@」,stu2);//stu1
stu2.name=@」stu2」;
NSLog(@」stu1:%@」,stu1);//stu1
NSLog(@」stu2:%@」,stu2);//stu2
[stu2 release];
}
#pragma mark GoodStudent inherit Student
GoodStudent.h
@interface GoodStudent : Student
@property (nonatomic,assign) int age;
+(id)goodStudentWithAge:(int)age name:(NSString *)name;
@end
GoodStudent.m
@implemrntation GoodStudent
+(id)goodStudentWithAge:(int)age name:(NSString *)name{
GoodStudent *good=[GoodStudent studentWithName:name];
//這樣寫返回的good是student對象
//因此student 方法應該是 Student *stu=[[[[self class]alloc]init]autorelease];
good.age=age;
return good;
}
-(id)copyWithZone:(NSZone *)zone{
//必定要調用父類的方法
GoodStudent *copy=[super copyWithZone:zone];
copy.age=self.age;
return copy;
}
-(NSString *)description {
return [NSString stringWithFomat:@」[name=%@,age=%i]」,self.name,_age];
//注意訪問不了_name ,_name是Student內部私有
}
@end
main.m
#import 「GoodStudent.h」
void goodStudentCopy(){
GoodStudent *stu1=[GoodStudent goodStudentWithAge:10 name;@」good1」];
GoodStudeent *stu2=[stu1 copy];
NSLog(@」stu1:%@」,stu1);
NSLog(@」stu2:%@」,stu2);
stu2.name=@」good2」;
stu2.age=@」11」;
NSLog(@」stu1:%@」,stu1);
NSLog(@」stu2:%@」,stu2);
}
key point: