• 深拷贝和浅拷贝(copy & mutableCopy)


    一、Copy

    1、NSObject的对象方法,返回值=通过NSCopying协议中copyWithZone:返回的对象。

    2、如果类实现NSCopying协议,copy很便利,否则会导致异常。

    3、NSObject本身不支持NSCopying协议,子类想调用copy,必须支持该协议,且实现copyWithZone:方法。

    4、子类实现copyWithZone:时,除了NSObject的子类,需先向上调用[super copyWithZone:zone],保证继承来的父类属性也能在copyWithZone:中初始化。

    举例如下;

    // Person继承自NSObject,Student继承自Person,均实现NSCopying协议
    
    @implementation Person
    - (id)copyWithZone:(NSZone *)zone
    {
        Person *p = [[[self class] alloc] init]; // <== 注意这里。如果不这样写,子类通过[super copyWithZone:zone]创建的是父类对象,会引发一系列的问题 
        p.userId = self.userId;
        return p;
    }
    @end
    
    @implementation Student
    - (id)copyWithZone:(NSZone *)zone
    {
        Student *s = [super copyWithZone:zone]; // 必须调用
        s.studentId = self.studentId;
        return s;
    }
    @end

    二、拷贝

    有两种类型的对象拷贝:浅拷贝和深拷贝。一般的拷贝是浅拷贝,浅拷贝创建新的collection却跟老collection共享对象。Collections包括数组、字典、集合等等。深拷贝就是拷贝了老collection且重新添加老collection内的对象,区别如下图:

    1、浅拷贝

    提供了许多浅拷贝collection的方式。创建浅拷贝时,老collection发送retain消息,拷贝指针成为新collection。例如以下方法就是浅拷贝:

    NSArray *shallowCopyArray = [someArray copyWithZone:nil];
     
    NSDictionary *shallowCopyDict = [[NSDictionary alloc] initWithDictionary:someDictionary copyItems:NO];

    不仅仅可以通过上面的方式,也通过copyWithZone:实现的copy,或者mutableCopyWithZone:方法,或者数组的initWithArray:copyItems:方法,均可实现浅拷贝。

    通过copy一个非mutable对象,新的collection和旧的collection地址一致,只是retainCount+1,为浅拷贝。

    通过mutableCopy,或者copy一个mutable对象,新collection的地址和旧collection的地址不一致,且为浅拷贝。

    2、深拷贝

    两种创建深拷贝的方式。

    1)通过initWithArray:copyItems:方法且第二个参数传YES,这种创建深拷贝的方式是给collection中的每个对象都发送copyWithZone:消息。如果没有实现NSCopying协议,试图拷贝collection的对象,会导致运行时错误。如果也实现了NSCopying协议,且协议中的copyWithZone:方法是深拷贝,那就是真正意义的深拷贝。然而如果copyWithZone:方法是浅拷贝。这类拷贝只是第一层次的深拷贝,如@[@[@[]],@[]],只是深拷贝了最外面[]中的元素。如下举例说明:

    NSArray *deepCopyArray=[[NSArray alloc] initWithArray:someArray copyItems:YES];

    以上方式也可用于其它的collection。

    2)如果需要真正的深拷贝,例如深拷贝数组,可以通过archive归档和unarchive解档 collection,使内容都实现NSCoding协议,举例如下:

    NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject:oldArray]];

    三、参考文档

    苹果官方:https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Collections/Articles/Copying.html

  • 相关阅读:
    WebEssentials 在vs2013 update5安装报错的解决方法.
    提高代码质量系列之三:我是怎么设计函数的?
    ValueInjecter----最好用的OOM(以微信消息转对象举例)
    我的第一个python程序--给2.x的print代码加上括号
    提高代码质量系列之二:重构小技巧——if篇
    提高代码质量系列之一:尽可能少写注释.
    Two-machine debugging
    12306个人敏感信息泄露
    纯手工秒杀VM,SE等虚拟机Handle
    2014版QQ个性显IP(源码+Bin)
  • 原文地址:https://www.cnblogs.com/zhouyi-ios/p/5223973.html
Copyright © 2020-2023  润新知