ios 中 实现对象复制(转载)

此文转载自http://keywind.me/?p=189

介绍两种方法使用NSCopying的协议copyWithZone方法去实现objects的copy。
你有两种方法通过实现NSCopying的协议copyWithZone创建copies:
(1).单纯使用alloc和init
(2).使用 NSCopyObject
对于如何选择,你需要考虑:
(1).我需要深拷贝还是浅拷贝
(2).我需要继承NSCopying的一些方法吗

1.深拷贝还是浅拷贝(override CopyWithZone)

拷贝一个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;
}
独立的拷贝

顾名思义,独立的拷贝只能是深拷贝,但通常我们需要把深拷贝和浅拷贝结合获得最佳效果。比如指针这种可以看成数据容器的object,我们需要深拷贝,而像委托这种复杂的object,浅拷贝会比较好,比如:

@interface Product  : NSObject <NSCopying>
{
    NSString  *productName;
     float price;
    id delegate;
}
 
@end

通过继承NSCopying,我们现在深拷贝一个Product,这时对应于这个深拷贝的Product的数据区的productName; float price; delegate;
三个object,我们看图:

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,下面这张图很好说明了这点:

我们看到NSCopyObject连retain count都直接复制过来,而copyWithZone则会修正它。

4.拷贝可变和不可变的Objects

NSCopying产生的是不可变的拷贝,不管其拷贝源是否可变。不可变的Object使用NSCopying很高效,NSCopying甚至可以去retain拷贝源,比如:

-  (id )copyWithZone : (NSZone  * )zone  {
     return  [self retain ];
}

而当我们要拷贝可变的objects时,则是使用NSMutableCopying,这个协议声明了mutableCopyWithZone方法。 可变的拷贝通常调用NSObject的方法mutableCopy,这个方法调用了 mutableCopyWithZone。

5 可变与不可变

参考:http://www.cnblogs.com/gaoxiao228/archive/2012/04/21/2462561.html

如果对一不可变对象复制,copy是指针复制(浅拷贝)和mutableCopy就是对象复制(深拷贝)。
如果是对可变对象复制,都是深拷贝,但是copy返回的对象是不可变的。

对于容器而言,其元素对象始终是指针复制。如果需要元素对象也是对象复制,就需要实现深拷贝

NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
    [NSKeyedArchiver archivedDataWithRootObject: array]];
trueDeepCopyArray是完全意义上的深拷贝,而deepCopyArray则不是,对于deepCopyArray内的不可变元素其还是指针复制
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值