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。
如果有不对的地方希望大家指出来
原文:
相关文章推荐
- Jmeter报告优化
- [leetcode] 336. Palindrome Pairs 解题报告
- 【转】async & await 的前世今生
- 【杂题】[POJ3222]Edge Pairing
- 简述OC中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是release,为什么?readwrite,reado
- 主题 : clang: error: linker command failed with exit code 1 (use -v to see invocation)
- LeetCode Climbing Stairs(经典动态规划)
- Makefile 没有规则创建目标“main.o”需要的目标“main.c”
- LeetCode 217. Contains Duplicate
- DailyNote
- Creating schema using Saiku Schema Designer
- Codeforces Round #353 (Div. 2) E. Trains and Statistic(求d[i][j]的和的最小值(1<=i<=n,i+1<=j<=n))
- SendKeys.SendWait()BUG解决方法
- Cookie未设置Domain
- Error:Failed to create directory 'C:\Users\Administrator\.gradle\caches\2.8\scripts\ijinit7_5jx13p26
- django错误 - Reason given for failure: CSRF cookie not set.
- 简单动态规划 climbing-stairs
- codeforces E. Trains and Statistic 线段树优化dp
- Execution failed for task ':dexDebug'
- poj2256人工智能?其实就是字符串处理啦