让我们复习一下内存管理的规则:“如果你使用alloc、copy或new方法获取了一个对象,则该对象的保留计数器的值为1,而且你要释放它。”既然叫copy方法,肯定就能创建对象的副本。copy消息会告诉对象创建一个全新的对象,并让新对象与接收copy消息的原对象完全一样。
一个对象如果想调用copy方法,需要实现NSCopying协议,该协议如下:
The NSCopying protocol declares a method for providing functional copies of an object. The exact meaning of “copy” can vary from class to class, but a copy must be a functionally independent object with values identical to the original at the time the copy was made. A copy produced with NSCopying is implicitly retained by the sender, who is responsible for releasing it.
NSCopying declares one method, copyWithZone:, but copying is commonly invoked with the convenience methodcopy. Thecopy method is defined for all objects inheriting fromNSObject and simply invokescopyWithZone: with the default zone.
Your options for implementing this protocol are as follows:
- Implement NSCopying using alloc and init... in classes that don’t inheritcopyWithZone:.
- Implement NSCopying by invoking the superclass’scopyWithZone: whenNSCopying behavior is inherited. If the superclass implementation might use theNSCopyObject function, make explicit assignments to pointer instance variables for retained objects.
- Implement NSCopying by retaining the original instead of creating a new copy when the class and its contents are immutable.
If a subclass inherits NSCopying from its superclass and declares additional instance variables, the subclass has to overridecopyWithZone: to properly handle its own instance variables, invoking the superclass’s implementation first.
下面通过一个例子来说明:
定义一个Cat类,初始化一个对象cat1,然后通过cat1调用copy方法来创建新的对象cat2
Cat.h文件
#import <Foundation/Foundation.h>
@interface Cat : NSObject<NSCopying>
{
NSString *_name; //名称
NSString *_color; //颜色
};
- (void) setName:(NSString*) name andColor:(NSString *) color;
- (NSString *) getName;
- (NSString *) getColor;
@end
Cat.m文件
#import "Cat.h"
@implementation Cat
- (void) setName:(NSString*) name andColor:(NSString *) color
{
_name = name;
_color = color;
}
- (NSString *) getName
{
return _name;
}
- (NSString *) getColor
{
return _color;
}
- (id) copyWithZone:(NSZone *)zone
{
Cat *newCat = [[Cat allocWithZone:zone] init];
[newCat setName:_name andColor:_color];
return newCat;
}
@end
main.m文件
#import <Foundation/Foundation.h>
#import "Cat.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
//通过alloc初始化创建对象
Cat *cat1 = [[Cat alloc] init];
[cat1 setName:@"Mimi" andColor:@"red"];
//通过copy方法创建新对象cat2
Cat *cat2 = [cat1 copy];
[cat2 setName:@"JJ" andColor:@"blue"];
NSLog(@"cat1 %@ %@ %@ ", cat1, [cat1 getName], [cat1 getColor]);
NSLog(@"cat2 %@ %@ %@ ", cat2, [cat2 getName], [cat2 getColor]);
}
return 0;
}
输出结果:
cat1 <Cat: 0x10010b5e0> Mimi red
cat2 <Cat: 0x10010bc30> JJ blue