zoukankan      html  css  js  c++  java
  • 深拷贝和浅拷贝(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

  • 相关阅读:
    VisualStudioAddIn2017.vsix的下载安装和使用
    数独计算程序的比较
    Ajax
    VSTO作品:OutlookMailViewer的下载和使用
    VB6实现Excel多工作簿数据合并
    组件中 data 为什么是一个函数?
    谈谈你对 keep-alive 的了解?
    父组件可以监听到子组件的生命周期吗?
    Vue 的父组件和子组件生命周期钩子函数执行顺序?
    谈谈你对 Vue 生命周期的理解?
  • 原文地址:https://www.cnblogs.com/zhouyi-ios/p/5223973.html
Copyright © 2011-2022 走看看