您的位置:首页 > 大数据 > 人工智能

copy和mutableCopy,retain

2016-05-18 16:05 579 查看

1 copy与retain的区别

copy:

copy是创建一个新对象(又称为内容拷贝或深拷贝);

copy时两个对象内容相同,地址不同。

新的对象引用计数为1,与旧有对象的引用计数无关。

copy减少对象对上下文的依赖。

retatin:

retain是创建一个指针(又称为指针拷贝或浅拷贝)

retain属性表示两个对象地址相同(建立一个指针,指针拷贝),内容相同。

retain对象的引用计数加1,与上下文有依赖。



2 系统的非容器类对象,这里指的是NSString,NSNumber等等一类的对象

对于可变类型变量(NSMutableString)copy相当于浅拷贝,mutableCopy相当于深拷贝。

mutablecopy也会产生一个新地址,位置在堆上,在mutalbecopy还会产生新地址。(深拷贝)

(待考证)copy会产生一个新的地址空间,位置在文字常量区上,如果在copy,地址就不会在变了。

copy方法,得到的是不可变对象,不管以前的是可变还是不可变。mutableCopy方法,得到的是可变对象,不管以前的是可变还是不可变。

对于一个mutableCopy的对象,接受者也要是一个可变类型变量(NSMutableString),才是一个可变类型的变量,才可以用相应的方法。

//origion 0x00007fbc485345a0
NSMutableString *mutablString = [NSMutableString stringWithString: @"origion"];
//origion 0xa6e6f696769726f7
NSString *StringForMutablStringCopy = [mutablString copy];
//origion  0xa6e6f696769726f7
NSMutableString *MutableStringForMutableStringCopy = [mutablString copy];
//origion 0x00007fbc485345e0
NSString *StringForMutablStringMutableCopy= [mutablString mutableCopy];
//origion 0x00007fbc48534620
NSMutableString *MutableStringForMutableStringMutableCopy = [mutablString mutableCopy];
//No visible @interface for 'NSString' declares the selector 'appending:'
[StringForMutablStringCopy appendString:@"mStringCopy"];//error
//No visible @interface for 'NSString' declares the selector 'appending:'
[StringForMutablStringMutableCopy appendString:@"mutablString!"];
//error Copy以后变成NSString
[MutableStringForMutableStringCopy appendString:@"mStringMCopy"];
//这个是正确的
[MutableStringForMutableStringMutableCopy appendString:@"mutablStringCopy"] ;


对于非可变类型变量(NSString)copy相当于浅拷贝,mutableCopy相当于深拷贝。

对于一个mutable拷贝的对象,接受者也要是一个可变类型变量(NSMutableString),才是一个可变类型的变量,才可以用相应的方法。

//origi 0x0000000104d971e0
NSString *string = @"origi";
//origi  0x0000000104d971e0
NSString *StringForStringCopy = [string copy];
//origi 0x0000000104d971e0
NSMutableString *MutableStringForStringCopy = [string copy];
//origi  0x00007fbc48534680
NSString *StringForStringMutableCopy= [string mutableCopy];
//origi 0x00007fbc485346e0
NSMutableString *MutableStringForStringMutableCopy = [string mutableCopy];
//No visible @interface for 'NSString' declares the selector 'appending:'
[StringForStringCopy appendString:@"mStringCopy"];//error
//No visible @interface for 'NSString' declares the selector 'appending:'
[StringForStringMutableCopy appendString:@"mutablString!"];
//error Copy以后还是NSString
[MutableStringForStringCopy appendString:@"mStringMCopy"];
//没问题,mutablecopy对应一个mutableString类型
[MutableStringForStringMutableCopy appendString:@"mutablStringCopy"] ;


3 系统的容器类对象指NSArray,NSDictionary等。

对于容器类本身,上面讨论的结论也是适用的。

对于容器内对象,其元素对象始终是指针复制。

如果需要元素对象也是对象复制,就需要实现深拷贝

//0x00007fb281446880
//[0]0x0000000109b6b120
//[1]0x0000000109b6b140
NSMutableArray *array=[[NSMutableArray alloc] initWithObjects:@"a",@"b", nil];
//0x00007fb2814468b0
//[0]0x0000000109b6b120
//[1]0x0000000109b6b140
NSMutableArray *deepCopyArray=[[NSMutableArray alloc] initWithArray: array copyItems: YES];
//0x00007fb281446de0
//[0]0xa000000000000611
//[1]0xa000000000000621
NSMutableArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
[NSKeyedArchiver archivedDataWithRootObject: array]];


当我们要实现一个自定义的类的时候就要遵循NSCopying,或者NSMutableCopying的协议才行

@interface Person : NSObject
@property (nonatomic,assign)NSMutableString *name;
@property (nonatomic,assign)NSString *sex;
@property (nonatomic,assign)NSString *age;
@property (nonatomic,assign)NSMutableString *height;
(id) copyWithZone:(NSZone *)zone {
NSLog(@"不可变");
NSLog(@"%d",zone);
copyPerson.height=[self.height copy ];
copyPerson.age=[self.age copy];
return copyPerson;
}
(id) mutableCopyWithZone:(NSZone *)zone
{
NSLog(@"%d",zone);
NSLog(@"可变");
Person *mutableCopyPerson=[[Person allocWithZone:zone] init];
mutableCopyPerson.name=[self.name mutableCopy];
mutableCopyPerson.sex=[self.sex copy];
mutableCopyPerson.height=[self.height mutableCopy ];
mutableCopyPerson.age=[self.age mutableCopy];
return mutableCopyPerson;
}

Person *_person=[[Person alloc] init];
_person.name=[NSMutableString stringWithString:@"唐余猛"];
_person.sex=@"男";
_person.height=[NSMutableString stringWithString:@"171"];
_person.age=@"24";
Person *copyPerson=[_person copy];//走的copyWithZone方法
Person *mutableCopy=[_person mutableCopy];//走的是mutableCopyWithZone方法


这时候疑问就来了,我设置一个可变的自定义类,内部的属性设置成不可变呢?答案很简单,mutableCopyWithZone和copyWithZone只会对这个对象拷贝,不会对这个对象的属性拷贝。那么这样的话mutableCopyWithZone,和copyWithZone用起来对一个自定义对象有什么区别呢。

这个是属于你对这个类的设计目标,比如你要设计一个Person类,如果不需要外界来修改它,那就是不可变的,

如果需要外界修改它,那就建个MutablePerson, 并加上相应的修改数据成员的方法, 这完全取决你的设计。

但是事实上,我们自己写代码时,很少遵循这种可变,不可变类的这种模式,通常都是建一个类,提供相应的设置方法。

事实上,只有CocoaTouch, string, dictionary, array这些基础的数据类型,才按这种模式来,一般的Model 类,基本不这么弄,

按这种模式来,写起来也麻烦,每种规则并不一是一定的。

对于自定义的类,如果我们想要实现copy的语义,我们需要实现NSCopying, NSMutableCopying这2个protocol。

如果有不对的地方希望大家指出来

原文:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: