copy语法

copy 和 mutableCopy

一个对象使用copy或者mutableCopy方法可以创建对象的副本

---------------

copy - 需要先实现NSCopying协议,创建的是不可变副本(如NSString,NSArray,NSDictionary)

---------------

mutableCopy - 需要先实现NSMutableCopying协议,创建的是可变副本(如NSMutableString,NSMutableArray,NSMutableDictionary,默认都已经实现)

像自己创建 的 Person Student 是不可以拷贝的,因为没有实现这两个协议中的一个。

---------------

深拷贝:内容拷贝,源对象和副本指向的是不同的两个对象,源对象引用计数器不变,副本计数器设置为1。内容拷贝。区别:有没有产生新对象。

image

---------------

浅拷贝:指针拷贝,源对象和副本指向的是同一个对象。对象的引用计数器+1,其实相当于做了一次retain操作。地址拷贝。

image

---------------

只有不可变对象创建的不可变副本(copy)才是浅复制,其他的都是深复制。

OC中copy语法存在的意义就是改变副本不影响源对象。

image

所以只跟调用的方法名有关系,跟源对象没关系。

内存管理回顾

image


#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

image

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);

}

image

image


key point:

image

原文地址:https://www.cnblogs.com/yesihoang/p/4561399.html