iOS深拷贝与浅拷贝

面试时,有小伙伴会被问到深浅拷贝的区别。对于这个问题,今天咱们闲话不表,直接上代码。

//非容器型对象

    NSString * testStr = @"123";
    NSString * copyStr = [testStr copy];// 这里是浅拷贝
    NSString * deepCopyStr = [testStr mutableCopy];//深拷贝
    
    NSLog(@"%@-----%@-------%@",testStr,copyStr,deepCopyStr);
    testStr = @"this is new str";
    NSLog(@"%@-----%@-------%@",testStr,copyStr,deepCopyStr);
    NSLog(@"%p----%p-----%p",testStr,copyStr,deepCopyStr);

打印结果1

2018-07-19 19:35:10.417102+0800 CopyTest[7756:285499] 123-----123-------123
2018-07-19 19:35:10.417295+0800 CopyTest[7756:285499] this is new str-----123-------123
2018-07-19 19:35:10.417408+0800 CopyTest[7756:285499] 0x10a5a00c8----0x10a5a0088-----0x604000440150
  • 分析1
    对于NSString类型的对象,使用copy 和 multableCopy方法都会返回一个新的对象,testStr的值更新后,不影响copyStr 和 deepCopyStr.

//Apple 类 没有实现NSCopying协议

    Apple *apple01 = [[Apple alloc] initWithColor:@"red" AndTaste:@"sweet"];
    Apple *apple02 =  [[Apple alloc] initWithColor:@"orange" AndTaste:@"sour"];
    NSArray *array = @[apple01,apple02];
    NSArray *array1 = [array copy]; //浅拷贝
    NSMutableArray *array2= [array mutableCopy]; //数组深拷贝 元素浅拷贝
    NSLog(@"%p-----%p------%p",array,array1,array2);
    NSLog(@"\narray---%@\narray1----%@\narray2------%@",array[0],array1[0],array2[0]);

打印结果2

2018-07-19 19:35:10.417552+0800 CopyTest[7756:285499] 0x600000225cc0-----0x600000225cc0------0x60000024e8b0
2018-07-19 19:35:10.417834+0800 CopyTest[7756:285499] 
array---<Apple: 0x600000225b20>
array1----<Apple: 0x600000225b20>
array2------<Apple: 0x600000225b20>
  • 分析2
    对于NSArray 而言,copy 是浅拷贝,因为array和 array1 都指向相同的内存地址,而multableCopy是深拷贝 因为array2指向了不同的内存地址。不过,需要注意一点,无论是深拷贝,还是浅拷贝,对于数组元素而言,都是浅拷贝,因为三个数组相同下标对应元素占用的内存地址是一样的。这里仅打印了三个数组中的第一个元素,以示说明。

//Orange 类 实现了NSCopying协议

    Orange *orange01 = [[Orange alloc] initWithColor:@"red" AndTaste:@"sweet"];
    Orange *orange02 =  [[Orange alloc] initWithColor:@"orange" AndTaste:@"sour"];
    NSArray *array3 = @[orange01,orange02];
    NSArray *array4 = [array3 copy];  //浅拷贝
    NSMutableArray *array5 = [array3 mutableCopy];//深拷贝 但数组元素是浅拷贝
    NSMutableArray *array6 = [[NSMutableArray alloc] initWithArray:array3 copyItems:YES];//深拷贝,且数组元素也是深拷贝
    NSLog(@"%p-----%p------%p-----%p",array3,array4,array5,array6);
    NSLog(@"\narray3---%@\narray4----%@\narray5-----%@\narray6----%@",array3[0],array4[0],array5[0],array6[0]);

打印结果3

2018-07-19 19:35:10.418013+0800 CopyTest[7756:285499] 0x600000225c20----0x600000225c20-----0x60000024eb50-----0x60000024ea30
2018-07-19 19:35:10.418168+0800 CopyTest[7756:285499] 
array3---<Orange: 0x600000225d80>
array4----<Orange: 0x600000225d80>
array5-----<Orange: 0x600000225d80>
array6----<Orange: 0x600000225ae0>
  • 分析3
    对于Orange类而言,遵循了NSCopying协议,且实现了copyWithZone方法,这样的话,array6就可以使用initWithArray: copyItems: 方法进行构造。因为Orange类可以进行copy操作,所以数组 array6 是array3深拷贝而来,且数组元素也是深拷贝。因为数组的内存地址 以及数组元素内存地址与array3 都不相同。
    如果不使用 initWithArray: copyItems 方法,也可以通过对array3 数组里的orange对象 进行遍历copy,也能实现同样的效果。
    NSMutableArray *array7 = [NSMutableArray array];
    for (Orange *orange in array3) {
        [array7 addObject:[orange copy]];
    }
    NSLog(@"%p----%p",array3,array7);
    NSLog(@"%@---%@",array3[0],array7[0]);

打印结果4

2018-07-19 20:14:42.125429+0800 CopyTest[8295:311564] 0x60400003e460----0x60000024a980
2018-07-19 20:14:42.126268+0800 CopyTest[8295:311564] <Orange: 0x60400003eda0>---<Orange: 0x600000421680>

总结:

  • Foundation框架下的类,并不是所有的都支持深拷贝,浅拷贝,只有那些遵循了NSCopying 或者 NSMultableCopying 协议的类,才可以进行拷贝操作。
  • 区别深浅拷贝的唯一标准就是:对象地址是否相同,如果相同,就是浅拷贝,反之则为深拷贝。
  • multableCopy 方法是执行深拷贝。如果该对象是容器类型,那么,返回的对象是深拷贝后的对象,但是这个对象里元素,还是之前对象里的元素,地址并没有变化。如果希望深拷贝后,返回的容器类型的对象里的元素也是深拷贝类型的,那么需要对容器内的元素也执行拷贝方法。

如果这篇博文能够帮助到你,那请帮我点赞哦。『demo』已放在github上,欢迎Start哦。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335

推荐阅读更多精彩内容

  • 1、对象拷贝有两种方式:浅复制和深复制。顾名思义,浅复制,并不拷贝对象本身,仅仅是拷贝指向对象的指针;深复制是直接...
    滴答大阅读 756评论 0 2
  • 首先提出一个问题 @property声明的NSString(或NSArray,NSDictionary),为什么经...
    hanzhansen阅读 440评论 0 4
  • 深拷贝和浅拷贝苹果官网上的解释如下: There are two kinds of object copying:...
    FlyElephant阅读 612评论 1 4
  • 大家好,我是西瓜,现居广州。在今年想要回顾梳理一下OC的相关知识点。今天就先从基础但不简单的深拷贝与浅拷贝开始吧。...
    watermelon_lp阅读 404评论 0 5
  • 浅拷贝:拷贝容易本身,返回一个对象,指向相同的内存地址. 深层复制:拷贝容器本身,返回一个对象,指向不同的内存地址...
    CoderShmily阅读 6,995评论 5 9