Copy语法
Oc中的Copy和mutableCopy方法:
Copy-需要先实现NSCopying协议,创建的是不可变的副本(如NSString、NSArray、NSDictionary)。
MutableCopy-需要实现NSMutableCopying协议,创建的是可变的副本 。
Tip:①copy语法的目的是产生一个副本使得改变副本时不会影响源对象。
②使用copy时要注意内存的管理。
MutableCopy和Copy的使用情况如下表所示:
源对象 | 调用的方法 | 获得的对象 |
NSArray | Copy | NSArray |
NSMutableArray | Mutable | NSMutableArray |
NSDictionary | Copy | NSDictionary |
NSMutableDictionary | Mutable | NSArrayDictionary |
NSString | Copy | NSString |
NSMutableString | Mutable | NSMutableString |
拷贝时可以分为以下两种情况:
深拷贝(内容拷贝):产生了新的对象,新对象的计数器置为1,源对象计数器不变。
浅拷贝(指针/地址拷贝):没有产生新的对象 ,只是将源对象的计数器+1,
Tip:当不可变的对象调用copy方法才是浅拷贝如下面的三种copy方式
源对象 | 调用的方法 | 获得的对象 |
NSArray | Copy | NSArray |
NSDictionary | Copy | NSDictionary |
NSString | Copy | NSString |
当想用自己的类使用copy语法时需要遵守NSCopying或NSMutableCopying协议并在.m文件中实现该协议
例如:Student的姓名拷贝
.h文件的内容:
@interface Student :NSObject <NSCopying>
// copy代表set方法会release旧对象、copy新对象
// 修改外面的变量,并不会影响到内部的成员变量
@property (nonatomic,copy) NSString *name;
+ (id)studentWithName:(NSString *)name;
@end
.m文件的内容
#import "Student.h"
@implementation Student
+ (id)studentWithName:(NSString *)name {
// 这里最好写[self class]
Student *stu = [[[[selfclass] alloc]init] autorelease];
stu.name = name;
return stu;
}
- (void)dealloc {
[_namerelease];
[superdealloc];
}
#pragma mark description方法内部不能打印self,不然会造成死循环
- (NSString *)description {
return [NSStringstringWithFormat:@"[name=%@]",_name];
}
#pragma mark copying协议的方法实现
// 这里创建的副本对象不要求释放
- (id)copyWithZone:(NSZone *)zone {
Student *copy = [[[selfclass] allocWithZone:zone]init];
//拷贝名字给副本对象
copy.name =self.name;
return copy;
}
@end
main函数中的实现为:
int main(int argc,const char * argv[])
{
@autoreleasepool {
Student *stu1 = [Student studentWithName:@"stu1"];
Student *stu2 = [stu1 copy];
stu2.name =@"stu2";
NSLog(@"stu1:%@", stu1);
NSLog(@"stu2:%@", stu2);
[stu2release];
}
return 0;
}
//当copy为浅拷贝时,setter实现时copy相当于retain
//copy代表set方法会release就对象,copy新对象。
@property(nonatmoic,copy)NSString *name;
以上代码相当与在类的实现时以下的两段代码:
- (void) setname :(NSString *)name{
if(_name !=name){
[_name release];
_name=[name copy]; //retain做修饰词则此处为retain
}
}
- (void) dealoc{
[_name release]
[super dealoc];
}
tip:建议:NSString一般使用copy策略,其他一般对象使用retain。