iPhone内存管理详细解说(五)
2013-06-04 11:51
274 查看
七:实现Object的Copy
这一节介绍两种方法使用NSCopying的协议copyWithZone方法去实现objects的copy。 你有两种方法通过实现NSCopying的协议copyWithZone创建copies:单纯使用alloc和init
使用 NSCopyObject
对于如何选择,你需要考虑:
我需要深拷贝还是浅拷贝
我需要继承NSCopying的一些方法吗
1.深拷贝还是浅拷贝
拷贝一个object也就是创建一个新的实例,并且初始化为拷贝源的值。对于像boolean,integer这类值,拷贝就是直接赋值。对于指针形的object就分为浅拷贝和深拷贝。浅拷贝是只创建一个新的指针,并指向同一块数据。深拷贝就是数据和指针都创建。我们来看:
深拷贝:
- (void)setMyVariable:(id)newValue { [myVariable autorelease]; myVariable = [newValue copy]; }
浅拷贝:
- (void)setMyVariable:(id)newValue { [myVariable autorelease]; myVariable = [newValue retain]; }
浅拷贝2:
- (void)setMyVariable:(id)newValue { myVariable = newValue; }
独立的拷贝
顾名思义,独立的拷贝只能是深拷贝,但通常我们需要把深拷贝和浅拷贝结合获得最佳效果。比如( NSString *productName;)指针这种可以看成数据容器的object,我们需要深拷贝,而像委托这种复杂的object,浅拷贝会比较好,比如:
@interface Product : NSObject <NSCopying> { NSString *productName; float price; id delegate; } @end
通过继承NSCopying,我们现在深拷贝一个Product,这时对应于这个深拷贝的Product的数据区的productName; float price; delegate; 三个object,我们看图:
![](http://keywind.me/images/2011/5/hybridcopy.gif)
productName的值不同,是深拷贝,而delegate的值相同,是浅拷贝,price无所谓深浅。
2.使用“alloc, init…”的方法
如果你的类么有继承NSCopying,那么你需要用alloc, init…和setter方法自己去实现copyWithZone,比如上面那个Product的例子,我们可以这样实现:
- (id)copyWithZone:(NSZone *)zone { Product *copy = [[[self class] allocWithZone: zone] initWithProductName:[self productName] price:[self price]]; [copy setDelegate:[self delegate]]; return copy; }
3.使用NSCopyObject()
如果你继承了NSCopying,没有像上面那样自己写copyWithZone,你要注意这个父类可能使用了NScopyObject函数去实现copyWithZone(你是继承过来的,当然也是了)。而NSCopyObject其实是浅拷贝,如NSCell这个类实现的copyWithZone:
- (id)copyWithZone:(NSZone *)zone { NSCell *cellCopy = NSCopyObject(self, 0, zone); /* Assume that other initialization takes place here. */ cellCopy->image = nil; [cellCopy setImage:[self image]]; return cellCopy; }
由于是浅拷贝,那么需要深拷贝的object就要额外对待。比如上面的image,我们在setter方法中需要:
- (void)setImage:(NSImage *)anImage { [image autorelease]; image = [anImage retain]; }
父类的NSCopyObject函数会拓展子类的实现,现在我们看NSCell的子类NSSlideCell怎么实现:
- (id)copyWithZone:(NSZone *)zone { id cellCopy = [super copyWithZone:zone]; /* Assume that other initialization takes place here. */ cellCopy->titleCell = nil; [cellCopy setTitleCell:[self titleCell]]; return cellCopy; }
父类的copyWithZone会被调用。
使用NSCopyObject还需要注意retain count,下面这张图很好说明了这点:
![](http://keywind.me/images/2011/5/internalrefcount.gif)
我们看到NSCopyObject连retain count都直接复制过来,而copyWithZone则会修正它。
4.拷贝可变和不可变的Objects
NSCopying产生的是不可变的拷贝,不管其拷贝源是否可变。不可变的Object使用NSCopying很高效,NSCopying甚至可以去retain拷贝源,比如:
- (id)copyWithZone:(NSZone *)zone { return [self retain]; }
而当我们要拷贝可变的objects时,则是使用NSMutableCopying,这个协议声明了mutableCopyWithZone方法。可变的拷贝通常调用NSObject的方法mutableCopy,这个方法调用了 mutableCopyWithZone。
相关文章推荐
- iPhone内存管理详细解说(一)
- iPad/iPhone内存管理四之viewDidUnload/dealloc详细解说
- iPhone内存管理详细解说(四)
- iPhone内存管理详细解说(三)
- iPhone内存管理详细解说(二)
- ipad/iphone内存管理三之NoAutorelease和Autorelease详细解说
- iPhone权限的详细解说(777,775 ,755和0755 的不同)
- iPhone必用&nbsp;新版installer详细使用教程
- C#重点知识详细解说(一)
- Win32下病毒设计入门详细解说
- 【php中的curl】php中curl的详细解说
- 详细解说 STL 排序(Sort)
- 详细解说 STL 排序(Sort)
- iPhone/Mac Objective-C内存管理教程和原理剖析(四)系统自动创建新的autorelease pool
- objective-c类别(Category)详细解说
- 详细解说 STL 排序(Sort)
- 详细解说STL string
- iPhone/Mac Objective-C内存管理教程和原理剖析(三)@property (retain)和@synthesize的默认实现
- 制作iPhone的SOAP应用的详细教程
- 详细解说 STL 排序(Sort)