copy:
返回由copyWithZone:返回的对象。
- (id)copy
返回值:
对象由NSCopying协议方法 copyWithZone:返回;
描述:
这是采用了NSCopying协议的对象的简便方法。如果对象没有实现copyWithZone:,将会抛出异常。NSObject自己并不支持 NSCopying协议,他的子类必须支持NSCopying协议,并实现 copyWithZone:方法。子类中的copyWithZone:应该先调用父类中的版本,除非子类是直接继承自NSObject
mutableCopy
返回由 mutableCopyWithZone:返回的对象,其中zone参数为nil。
- (id)mutableCopy;
返回值:
对象由NSMutableCopying协议方法 mutableCopyWithZone:返回,zone参数为nil。
描述:
这是采用了 NSMutableCopying协议的类的便利方法,如果这个类型没有实现mutableCopyWithZone:方法,将会产生异常。
验证:非可变对象不能用mutableCopy;
例子:
CopyTestObject 继承自 NSObject
代码:
CopyTestObject* obj = [[CopyTestObject alloc] init];
CopyTestObject* copyObj = [obj copy];
NSLog(@"obj address:%p",obj);
NSLog(@"obj address:%p",copyObj);
运行正常,输出
obj address:0xa06a6a0
obj address:0xa069b80
代码:
CopyTestObject* obj = [[CopyTestObject alloc] init];
CopyTestObject* mutableCopyObj = [obj mutableCopy];
出现异常NSInvalidArgumentException
reason: '-[CopyTestObject mutableCopyWithZone:]: unrecognized selector sent to instance 0x9a847d0'
验证:可变对象,用copy得到的为非可变对象。用mutableCopy得到可变对象。
例子2:
NSArray* array = [[NSArray alloc] init];
NSArray* copyArray = [array copy];
NSMutableArray* mutArray = [[NSMutableArray alloc] init];
NSMutableArray* copyMutArray = [mutArray copy];
NSMutableArray* mutArray2 = [[NSMutableArray alloc] init];
NSMutableArray* copyMutArray2 = [mutArray mutableCopy];
NSLog(@"array class:%@",[NSString stringWithUTF8String:object_getClassName(array)]);
NSLog(@"copyArray class:%@",[NSString stringWithUTF8String:object_getClassName(copyArray)]);
NSLog(@"mutArray class:%@",[NSString stringWithUTF8String:object_getClassName(mutArray)]);
NSLog(@"copyMutArray class:%@",[NSString stringWithUTF8String:object_getClassName(copyMutArray)]);
NSLog(@"mutArray2 class:%@",[NSString stringWithUTF8String:object_getClassName(mutArray2)]);
NSLog(@"copyMutArray2 class:%@",[NSString stringWithUTF8String:object_getClassName(copyMutArray2)]);
输出:
2014-04-11 10:38:27.257 testCopy[4759:a0b] array class:__NSArrayI
2014-04-11 10:38:27.257 testCopy[4759:a0b] copyArray class:__NSArrayI
2014-04-11 10:38:27.257 testCopy[4759:a0b] mutArray class:__NSArrayM
2014-04-11 10:38:27.258 testCopy[4759:a0b] copyMutArray class:__NSArrayI
2014-04-11 10:38:27.258 testCopy[4759:a0b] mutArray2 class:__NSArrayM
2014-04-11 10:38:27.258 testCopy[4759:a0b] copyMutArray2 class:__NSArrayM
NSCopying协议:
NSCopying协议声明了一个方法来拷贝一个对象。拷贝的确切意义可能根据不同个类型而变化,但是拷贝的对象必须是一个功能独立的对象,其中包含的值和原对象相同在拷贝完成时。拷贝产生的对象被调用者保留,以在适当的时候释放他。
NSCopying定义了一个方法copyWithZone:,但是拷贝通常通过简便函数copy调用。copy函数在所有继承自NSObject的对象中都有定义,用来方便的调用copyWithZone:,其中参数为默认zone(内存区域)。
在如下情况你可以选择实现协议:
1.实现NSCopying来使用alloc和init,在那些没有继承copyWithZone:的类别中。
3.实现NSCopying,在某些内容不可变的类别中,以保留计数来代替创建一个新的拷贝。(自定义对象的拷贝含义)
如果子类从父类继承NSCopying,而且声明了额外的成员变量,子类必须去重写copyWithZone:,以正确的操作自己的成员变量,当然要先调用父类的实现。
实例方法:
- (id)copyWithZone:(NSZone *)zone
返回一个新的实例,这个实例是发送者的拷贝。
参数:
内存中被分配给新实例的一块区域,如果zone的值为NULL,则新实例从默认的区域中分配,这块默认的区域由NSDefaultMallocZone返回。
描述:
拷贝返回一个不可变类型,如果接收者需要考虑可变与不可变。否则复制的具体情况由类型决定。
NSMutableCopying协议:
NSMutableCopying协议声明了了一个方法来提供可变对象的副本。只有定义了可变与不可变差别的类型能采用改协议。那些没有这些差别的类型,应采取NSCopying协议。
NSMutableCopying协议中声明了一个方法,mutableCopyWithZone:,但是可变拷贝通常通过便利方法mutableCopy来调用。mutableCopy方法在所用的NSObject对象中都有定义,以便更方便的调用mutableCopyWithZone:方法。
如果子类从父类继承NSMutableCopying协议,并且声明了额外的实例变量,子类需要去重构 mutableCopyWithZone:来正确的操作他自己的实例变量,当然首先应该调用父类的实现。
实例方法:
- (id)mutableCopyWithZone:(NSZone *)zone
参数
zone
内存中被分配给新实例的一块区域,如果zone的值为NULL,则新实例从默认的区域中分配,这块默认的区域由NSDefaultMallocZone返回。
描述
这个拷贝返回的是可变对象,无论原对象是可变的或不可变的。
关于数组的深浅拷贝
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Collections/Articles/Copying.html
无论用copy还是mutablecopy得到的都是数组的浅拷贝。
数组的深拷贝
NSArray *deepCopyArray=[[NSArray alloc] initWithArray:someArray copyItems:YES];
其中数组中的元素要实现方法:
- (id)copyWithZone:(NSZone *)zone
验证例子:
@interface CopyTestObject : NSObject
@property (nonatomic, copy)NSString* thename;
@property (nonatomic, retain)NSString* myname;
@end
@implementation CopyTestObject
- (id)copyWithZone:(NSZone *)zone
{
CopyTestObject *result = [[[self class] allocWithZone:zone] init];
result.myname = [self.myname copy];
result.thename = [self.thename copy];
return result;
}
@end
NSMutableArray* mutArray =[[NSMutableArray alloc] init];
{
CopyTestObject* obj = [[CopyTestObject alloc] init];
obj.thename = @"name1111111";
obj.myname = @"myname1111111";
[mutArray addObject:obj];
}
{
CopyTestObject* obj = [[CopyTestObject alloc] init];
obj.thename = @"name22222222";
obj.myname = @"myname22222222";
[mutArray addObject:obj];
}
NSArray* copyArray = [[NSMutableArray alloc] initWithArray:mutArray copyItems:YES];
CopyTestObject* obj1 = [mutArray objectAtIndex:0];
obj1.thename = @"name change";
obj1.myname = @"myname change";
for (CopyTestObject* obj in mutArray) {
NSLog(@"mutArray:%@ %@",obj.thename,obj.myname);
}
for (CopyTestObject* obj in copyArray) {
NSLog(@"copyArray:%@ %@",obj.thename,obj.myname);
}
输出:
2014-04-11 10:49:12.581 testCopy[4779:a0b] mutArray:name change myname change
2014-04-11 10:49:12.582 testCopy[4779:a0b] mutArray:name22222222 myname22222222
2014-04-11 10:49:12.582 testCopy[4779:a0b] copyArray:name1111111 myname1111111
2014-04-11 10:49:12.582 testCopy[4779:a0b] copyArray:name22222222 myname22222222