copy语法的目的:改变副本的时候,不会影响到源对象;
深拷贝:内容拷贝,会产生新的对象。新对象计数器置为1,源对象计数器不变。
浅拷贝:指针拷贝,不会产生新的对象。源对象计数器+1。
拷贝有下面两个方法实现拷贝:
- (id)copy; - (id)mutableCopy;
对象要实现copy,必须实现<NSCopying>协议
数组,字典,字符串都已经实现了<NSCopying>协议,以下以字符串为例:
1.不可变字符串调用copy实现拷(浅拷贝)
NSString *string = [[NSString alloc] initWithFormat:@"abcde"]; // copy产生的是不可变副本,由于源对象本身就不可变,所以为了性能着想,copy会直接返回源对象本身 // 源对象计数器会+1 // 在浅拷贝情况下,copy其实就相当于retain NSString *str = [string copy];
2.不可变字符串调用mutableCopy实现拷贝,(深拷贝)
NSString *string = [[NSString alloc] initWithFormat:@"abcd"]; // 产生了一个新的对象,计数器为1。源对象的计数器不变。 NSMutableString *str = [string mutableCopy];//此时存在两个对象// str:1和// string:1 // str和string不是相同对象 // NSLog(@"%i", str == string);//0 [str appendString:@" abcd"];//修改str不影响string NSLog(@"string:%@", string); NSLog(@"str:%@", str);
3.可变字符串调用copy实现拷贝(深拷贝)
NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10]; // 会产生一个新对象,str计数器为1 NSString *str = [string copy];
4.可变字符串的MutableCopy(深拷贝)
NSMutableString *string = [NSMutableString stringWithFormat:@"age is %i", 10]; // 会产生一个新对象,str计数器为1 NSMutableString *str = [string mutableCopy]; [str appendString:@"1234"];//修改新对象不影响原对象 NSLog(@"str:%@", str); NSLog(@"string:%@", string);
5.拷贝自定义对象,下面以Student对象为例
a.Student要实现copy,必须实现<NSCopying>协议
b.实现<NSCopying>协议的方法:
- (id)copyWithZone:(NSZone *)zone
Student.h文件
@interface Student : NSObject <NSCopying> // copy代表set方法会release旧对象、copy新对象 // 修改外面的变量,并不会影响到内部的成员变量 // 建议:NSString一般用copy策略,其他对象一般用retain @property (nonatomic, copy) NSString *name; + (id)studentWithName:(NSString *)name; @end
Student.m文件
#import "Student.h" @implementation Student + (id)studentWithName:(NSString *)name { // 这里最好写[self class] Student *stu = [[[[self class] alloc] init] autorelease]; stu.name = name; return stu; } - (void)dealloc { [_name release]; [super dealloc]; } #pragma mark description方法内部不能打印self,不然会造成死循环 - (NSString *)description { return [NSString stringWithFormat:@"[name=%@]", _name]; } #pragma mark copying协议的方法 // 这里创建的副本对象不要求释放 - (id)copyWithZone:(NSZone *)zone { Student *copy = [[[self class] allocWithZone:zone] init]; // 拷贝名字给副本对象 copy.name = self.name; return copy; } @end
拷贝Student
Student *stu1 = [Student studentWithName:@"stu1"]; Student *stu2 = [stu1 copy]; stu2.name = @"stu2"; NSLog(@"stu1:%@", stu1); NSLog(@"stu2:%@", stu2); [stu2 release];
小结:
建议:NSString一般用copy策略,其他对象一般用retain;
只有一种情况是浅拷贝:不可变对象调用copy方法时,其他情况都为深拷贝;
时间: 2024-11-05 16:47:57