OC 深拷贝与浅拷贝详解

概述


  • 拷贝:复制一个与源对象内容相同的对象
  • 实现拷贝,需要遵守以下两个协议

    • NSCopying
    • NSMutableCopying
  • 拷贝返回对象的种类

    • 可变,mutableCopy消息返回的对象
    • 不可变,copy消息返回的对象
  • 拷贝的种类

    • 浅拷贝,只是复制了一个指向源对象的指针,未创建对象,未分配内存
    • 深拷贝,复制了源对象,创建了新对象,分配了内存
  • 注意

    • 系统对容器类的对象与非容器类的对象的内存处理是不同的,即当一个没有被其他对象强引用的对象从容器中移除后,该对象就销毁

Copy与Retain


  • copy

    • 是创建一个新的对象,内容拷贝
    • copy表示的是两个对象的内容相同, 新对象的引用计数为1
    • 与旧对象的引用计数无关,就对象没有变化
    • copy减少了对象对上下文的
  • retain

    • 创建的是一个指针,指针拷贝
    • 对象地址相同,内容固然相同
    • 对象的引用计数+1

不同对象的拷贝行为


  • 非容器对象(如NSString))

    • 对于不可变对象

      • 规则

        • copy,浅拷贝(指针复制)
        • mutableCopy,深拷贝(对象复制),返回对象可变(产生新的 可变对象)
      • 示例

        - (void)imutableInstanceCopy
        {
            NSString *string = @"Welcome to Xcode";
        
            //copy,浅拷贝
            NSString *stringCopy = [string copy]; //mutableCopy,返回的对象可变 NSMutableString *stringMutableCopy = [string mutableCopy]; [stringMutableCopy appendString:@"!"]; //string与stringCopy的内存地址相同 NSLog(@"string: %p", string); NSLog(@"strongCopy: %p", stringCopy); //string与stringMutableCopy的内存地址不同,分配了新的内存 NSLog(@"stringMCopy:%p", stringMutableCopy); }
    • 对于可变对象

      • 规则

        • copy,深拷贝(对象复制),返回对象不可变
        • mutableCopy,深拷贝(对象复制)
      • 示例

        - (void)mutableInstanceCopy
        {
            NSMutableString *mutableString = [NSMutableString stringWithString: @"Welcome to Xcode"];
        
            //深拷贝,返回对象不可变 NSString *stringCopy = [mutableString copy]; NSMutableString *mutableStringCopy = [mutableString copy]; //运行时,此句会报错,错误信息“Attempt to mutate immutable object with appendString:” [mutableStringCopy appendString:@"~~~"]; //深拷贝,返回对象可变 NSMutableString *stringMutableCopy = [mutableString mutableCopy]; [stringMutableCopy appendString:@"!"]; //三者与mutableString的内存地址都不同 NSLog(@"mutableString: %p", mutableString); NSLog(@"string: %p", stringCopy); NSLog(@"mutableStringCopy: %p", mutableStringCopy); NSLog(@"stringMutbleCopy:%p", stringMutableCopy); }
  • 容器对象(NSArray

    • 遵循非容器对象的拷贝原则
    • 注意

      • 容器内的元素是指针赋值(浅拷贝)
      • 示例

        - (void)containerInstanceShallowCopy
        {
            NSArray *array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"Welcome"],@"to",@"Xcode",nil]; //浅拷贝 NSArray *arrayCopy = [array copy]; //深拷贝 NSMutableArray *arrayMutableCopy = [array mutableCopy]; NSLog(@"array: %p", array); NSLog(@"arrayCopy: %p", arrayCopy); NSLog(@"arrayMutableCopy: %p", arrayMutableCopy); //容器内的对象是浅拷贝,即它们在内存中只有一份 NSMutableString *testString = [array objectAtIndex:0]; [testString appendString:@" you"]; //三个数组的内容同时改变 NSLog(@"array[0]: %@", array[0]); NSLog(@"arrayCopy[0]: %@", arrayCopy[0]); NSLog(@"arrayMutableCopy[0]: %@", arrayMutableCopy[0]); }
    • 实现真正意义上的深复制

      - (void)containerInstanceDeepCopy
      {
          NSArray *array = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"Welcome"],@"to",@"Xcode",nil]; //数组内对象是指针复制 NSArray *deepCopyArray = [[NSArray alloc] initWithArray:array]; //真正以上的深复制,数组内对象是对象复制 NSArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array]]; NSLog(@"array: %p", array); NSLog(@"deepCopyArray: %p", deepCopyArray); NSLog(@"trueDeepCopyArray: %p", trueDeepCopyArray); //改变array的第一个元素 [[array objectAtIndex:0] appendString:@" you"]; //只影响deepCopyArray数组的第一个元素 NSLog(@"array[0]: %@", array[0]); NSLog(@"arrayCopy[0]: %@", deepCopyArray[0]); //不影响trueDeepCopyArray数组的第一个元素,是真正意义上的深拷贝 NSLog(@"arrayMutableCopy[0]: %@", trueDeepCopyArray[0]); }
  • 自定义对象

    • 在定义对象要实现拷贝,需要遵守NSCoping与NSMutableCoping协议,并实现以下方法

      • - (id)copyWithZone:(NSZone *)zone,可变拷贝
      • - (id)mutableCopyWithZone:(NSZone *)zone,不可变拷贝
    • 示例(自定对象Person的拷贝)

      • 遵守协议,设置成员属性

        @interface Person : NSObject <NSCopying, NSMutableCopying>
        /**姓名*/
        @property (nonatomic, copy) NSMutableString *name;
        /**地址*/ @property (nonatomic, copy) NSString *address; /**年龄*/ @property (nonatomic, assign) NSInteger age; @end
      • 重写初始化方法

        - (instancetype)init
        {
            if (self = [super init]) { self.name = [[NSMutableString alloc] initWithString:@"XiaoYaowang"]; self.address = @"空山新雨后"; self.age = 3; } return self; }
      • 实现- (id)copyWithZone:(NSZone *)zone

        - (id)copyWithZone:(NSZone *)zone
        {
            Person *p = [[[self class] allocWithZone:zone] init];
            p.name = [self.name copy]; p.address = [self.address copy]; p.age = self.age; return p; }
      • 实现- (id)mutableCopyWithZone:(NSZone *)zone

        - (id)mutableCopyWithZone:(NSZone *)zone
        {
            Person *p = [[[self class] allocWithZone:zone] init];
            //注意,此处是mutableCopy方法
            p.name = [self.name mutableCopy]; p.address = [self.address copy]; p.age = self.age; return p; }

---恢复内容结束---

转载于:https://www.cnblogs.com/funny11/p/4948988.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Objective-C 中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是用于复制对象的两种不同方式。 浅拷贝是指创建一个新的对象,该对象与原始对象共享数据的内存地址。换句话说,新对象只是原始对象的一个引用,对新对象的修改也会影响原始对象。在 Objective-C 中,可以使用 `copy` 方法来执行浅拷贝深拷贝是指创建一个新的对象,并且复制原始对象的所有数据。这意味着新对象有自己的内存地址,对新对象的修改不会影响原始对象。在 Objective-C 中,可以使用 `mutableCopy` 方法来执行深拷贝。 需要注意的是,深拷贝只会复制对象本身,而不会递归地复制对象所包含的其他对象。如果需要对对象的所有数据进行递归复制,可以通过实现 NSCopying 协议来自定义深拷贝操作。 下面是一个示例代码,演示了如何执行浅拷贝深拷贝: ```objective-c #import <Foundation/Foundation.h> @interface Person : NSObject <NSCopying> @property (nonatomic, copy) NSString *name; @end @implementation Person - (instancetype)copyWithZone:(NSZone *)zone { Person *copy = [[Person allocWithZone:zone] init]; copy.name = self.name; return copy; } @end int main(int argc, const char * argv[]) { @autoreleasepool { Person *person1 = [[Person alloc] init]; person1.name = @"John"; // 浅拷贝 Person *person2 = [person1 copy]; NSLog(@"person1: %@, person2: %@", person1.name, person2.name); // 输出:person1: John, person2: John // 深拷贝 Person *person3 = [person1 mutableCopy]; person3.name = @"Emily"; NSLog(@"person1: %@, person3: %@", person1.name, person3.name); // 输出:person1: John, person3: Emily } return 0; } ``` 在上面的示例中,使用 `copy` 方法执行了浅拷贝操作,`mutableCopy` 方法执行了深拷贝操作。注意,为了实现深拷贝,我们在 `Person` 类中遵循了 NSCopying 协议,并重写了 `copyWithZone:` 方法来自定义深拷贝操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值