美文网首页
iOS开发中的深拷贝与浅拷贝

iOS开发中的深拷贝与浅拷贝

作者: ZZYZLY | 来源:发表于2017-12-12 13:57 被阅读15次

今天在一个技术群里看到关于copymutableCopy的讨论,感觉那个人说的不全面,今天顺便找个时间弄些例子重新总结下:

一、深拷贝就是拷贝对象本身到新的内存中,生成一个新的对象。浅拷贝就是拷贝指针,并不拷贝对象本身,原有的对象引用计数+1

二、非集合类对象copy与mutableCopy

NSString *str = @"123";
NSLog(@"%p", str);

NSString *copyStr = [str copy];
NSLog(@"%p", copyStr);

NSString *mutableCopyStr = [str mutableCopy];
NSLog(@"%p", mutableCopyStr);

2017-12-12 [2080:42478] 0x1076fa940
2017-12-12 [2080:42478] 0x1076fa940
2017-12-12 [2080:42478] 0x60400004e4f0
非集合类不可变对象的copy是浅拷贝,内存地址不变,mutableCopy是深拷贝
NSMutableString *str = [NSMutableString stringWithFormat:@"123"];
NSLog(@"%p", str);

NSString *copyStr = [str copy];
NSLog(@"%p", copyStr);

NSMutableString *mutableCopyStr = [str mutableCopy];
NSLog(@"%p", mutableCopyStr);

2017-12-12 [2174:48858] 0x6040002463f0
2017-12-12 [2174:48858] 0xa000000003332313
2017-12-12 [2174:48858] 0x60000024cc00
非集合类可变对象进行copy和mutableCopy都是深拷贝,内存地址发生改变。copy操作发生内存地址改变很好理解(从一个可变对象变成了不可变对象),为什么mutableCopy也是深拷贝呢?猜测认为,可变对象后面有可能是要改变的,如果执行的是浅拷贝(指针拷贝),那么原对象或者mutableCopy出来的对象如果其中一个发生了改变,都会影响另外一个,所以应该是新创建一个对象。

三、集合类对象copy与mutableCopy

NSArray *array = @[@"123", @"asf"];
NSLog(@"%p", array);

NSArray *copyArray = [array copy];
NSLog(@"%p", copyArray);

NSMutableArray *mutableCopyArray = [array mutableCopy];
NSLog(@"%p", mutableCopyArray);

2017-12-12 [2340:64439] 0x604000039660
2017-12-12 [2340:64439] 0x604000039660
2017-12-12 [2340:64439] 0x6040000592c0
同非集合类对象,集合类不可变对象的copy也是浅拷贝,mutableCopy是深拷贝
NSMutableArray *array = [@[@"123", @"asf"] mutableCopy];
NSLog(@"%p", array);

NSArray *copyArray = [array copy];
NSLog(@"%p", copyArray);

NSMutableArray *mutableCopyArray = [array mutableCopy];
NSLog(@"%p", mutableCopyArray);

2017-12-12 [2392:70043] 0x60000024d4d0
2017-12-12 [2392:70043] 0x600000032fe0
2017-12-12 [2392:70043] 0x60000024c900
如上,不论是copy还是mutableCopy 都对array进行了深拷贝。类似非集合类对象。

四、集合类的深拷贝

集合类的对象,在执行copy或者mutableCopy方法进行深拷贝的时候,仅仅是拷贝对象本身,对象内的元素仍然是浅拷贝(指针复制)
NSMutableString *string = [NSMutableString stringWithFormat:@"123"];
NSMutableArray *subArray = [@[@"123", @"adsf"] mutableCopy];

NSMutableArray *array = [NSMutableArray arrayWithObjects:string, subArray, nil];

NSArray *copyArray = [array copy];
NSLog(@"copyArray = %@", copyArray);

[string appendFormat:@"456"];
[subArray removeObjectAtIndex:0];
NSLog(@"copyArray = %@", copyArray);

2017-12-12 [3528:131325] copyArray= (
123,
    (
      123,
      adsf
    )
)   
2017-12-12 [3528:131325] copyArray = (
123456,
    (
      adsf
    )
)
如上,如果我们修改了copyArray里面的string和subArray的话,copyArray内的对象也会跟着改变.

对集合内的对象也执行深拷贝可以使用如下两种方法:

  • NSArray *copyArray = [[NSArray alloc] initWithArray:array copyItems:YES];
    NSMutableString *string = [NSMutableString stringWithFormat:@"123"];
    NSMutableArray *subArray = [@[@"123", @"adsf"] mutableCopy];

    NSMutableArray *array = [NSMutableArray arrayWithObjects:string, subArray, nil];

    NSArray *copyArray = [[NSArray alloc] initWithArray:array copyItems:YES];
    NSLog(@"copyArray = %@", copyArray);

    [string appendFormat:@"456"];
    [subArray removeObjectAtIndex:0];
    NSLog(@"copyArray = %@", copyArray);
    
    2017-12-12 [3625:137732] copyArray = (
     123,
       (
         123,
         adsf
        )
     )
    
    2017-12-12 [3625:137732] copyArray = (
    123,
        (
          123,
          adsf
        )
    )
如上,发现copyArray内的对象并不会随着改变。但是如果集合内的对象里面的元素也改变了呢?
NSMutableString *string = [NSMutableString stringWithFormat:@"123"];
NSMutableArray *subArray = [@[string, @"adsf"] mutableCopy]; //这里在可变的数组里面加入可变的字符串string

NSMutableArray *array = [NSMutableArray arrayWithObjects:string, subArray, nil];

NSArray *copyArray = [[NSArray alloc] initWithArray:array copyItems:YES];
NSLog(@"copyArray = %@", copyArray);

[string appendFormat:@"456"];
[subArray removeObjectAtIndex:0];
NSLog(@"copyArray = %@", copyArray);

2017-12-12 [3687:144061] copyArray = (
123,
    (
      123,
      adsf
    )
)

2017-12-12 [3687:144061] copyArray = (
123,
    (
      123456,
      adsf
    )
)
这个时候我们发现如果array内部的subArray里面的string发生了改变,是会影响到copyArray的.
initWithXXXX: copyItems:这个方法只能提供一层深拷贝,并不是真正的深拷贝。这个方法是对集合内每个对象都发送copyWithZone:消息,如果集合内的对象遵守了NSCopying:协议那么会深拷贝到新的集合对象内,如果没有遵守,会出错。

那么怎么才能实现完全深拷贝呢:

  • NSArray *deepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array]];

这种将将集合进行归档(archive),然后再解档(unarchive),才可以实现完全深拷贝。

NSMutableString *string = [NSMutableString stringWithFormat:@"123"];
NSMutableArray *subArray = [@[string, @"adsf"] mutableCopy];

NSMutableArray *array = [NSMutableArray arrayWithObjects:string, subArray, nil];

NSArray *copyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:array]];
NSLog(@"copyArray = %@", copyArray);

[string appendFormat:@"456"];
[subArray removeObjectAtIndex:0];
NSLog(@"copyArray = %@", copyArray);

2017-12-12 [3736:149666] copyArray = (
123,
    (
      123,
      adsf
    )
)

2017-12-12 [3736:149666] copyArray = (
123,
    (
      123,
      adsf
    )
)

相关文章

  • Objective-C中的浅拷贝和深拷贝

    Objective-C中的浅拷贝和深拷贝IOS开发之深拷贝与浅拷贝(mutableCopy与Copy)详解iOS ...

  • 深拷贝和浅拷贝

    1: iOS开发 深拷贝与浅拷贝 2: iOS 浅谈:深.浅拷贝与copy.strong 3: iOS开发——深...

  • copy和mutablecopy

    Objective-C中的浅拷贝和深拷贝 - CocoaChina_让移动开发更简单 iOS 浅谈:深.浅拷贝与c...

  • iOS 图文并茂的带你了解深拷贝与浅拷贝

    iOS 图文并茂的带你了解深拷贝与浅拷贝 iOS 图文并茂的带你了解深拷贝与浅拷贝

  • iOS开发深拷贝与浅拷贝的关系

    IOS开发之深拷贝与浅拷贝(mutableCopy与Copy)详解 copy与retain的区别: copy是创建...

  • iOS深拷贝(MutableCopy)与浅拷贝(Copy)的区别

    深拷贝和浅拷贝的概念 iOS中有深拷贝和浅拷贝的概念,那么何为深拷贝何为浅拷贝呢?浅拷贝:浅拷贝并不拷贝对象本身,...

  • iOS 深浅拷贝

    iOS深拷贝与浅拷贝的区别 深拷贝与浅拷贝的概念:(我的理解,望不吝赐教) 浅拷贝:只copy一份对象的指针,指向...

  • JS中的深拷贝与浅拷贝

    知乎:js中的深拷贝和浅拷贝? 掘金: js 深拷贝 vs 浅拷贝 前言 首先深拷贝与浅拷贝只针对 Object,...

  • iOS学习之copy属性分析

    小结第一篇,来总结一下iOS开发中有关copy的知识点。 iOS中,深拷贝和浅拷贝有什么不同? 浅拷贝 所谓的浅拷...

  • iOS之深拷贝与浅拷贝

    深拷贝与浅拷贝是在内存管理中非常重要的概念,理解好深拷贝和浅拷贝也有助于加深对iOS的内存管理的理解。 深拷贝与浅...

网友评论

      本文标题:iOS开发中的深拷贝与浅拷贝

      本文链接:https://www.haomeiwen.com/subject/bctnixtx.html