最近在简书看到了一篇关于iOS深浅拷贝的博客,下面做一下学习总结:

非集合类对象的copy和mutableCopy

非集合类对象指NSString、NSNumber、NSMutableString等对象。对immutable(不可变对象)进行copy操作,就是简单的指针拷贝,进行mutableCopy操作时,是进行内容复制。对于mutable(可变对象)无论进行copy还是mutableCopy都是内容拷贝。

// 非集合类对象的copy和mutablecopy
// 1.不可变对象
NSString *str = @"hello";
NSString *str_copy = str.copy;
NSMutableString *str_mutecopy = str.mutableCopy;
[str_mutecopy appendString:@" world"]; NSLog(@"%@---%p----%@",str,str,[str class]);
NSLog(@"%@---%p----%@",str_copy,str_copy,[str_copy class]);
NSLog(@"%@---%p----%@",str_mutecopy,str_mutecopy,[str_mutecopy class]);
NSLog(@"\n"); // 输出
// 2018-05-19 22:26:17.847234+0800 深浅拷贝练习[5861:566828] hello---0x100002060----__NSCFConstantString
// 2018-05-19 22:26:17.847418+0800 深浅拷贝练习[5861:566828] hello---0x100002060----__NSCFConstantString
// 2018-05-19 22:26:17.847475+0800 深浅拷贝练习[5861:566828] hello world---0x10053bab0----__NSCFString //2.可变对象
NSMutableString *str_mute = [NSMutableString stringWithString:@"hello"];
NSString *str_mute_copy = str_mute.copy;
NSMutableString *str_mute_mutecopy = str_mute.mutableCopy;
[str_mute appendString:@" world"];
[str_mute_mutecopy appendString:@" Objective-C"]; NSLog(@"%@---%p----%@",str_mute,str_mute,[str_mute class]);
NSLog(@"%@---%p----%@",str_mute_copy,str_mute_copy,[str_mute_copy class]);
NSLog(@"%@---%p----%@",str_mute_mutecopy,str_mute_mutecopy,[str_mute_mutecopy class]); // 输出
// 2018-05-19 22:26:17.847544+0800 深浅拷贝练习[5861:566828] hello world---0x10053bc30----__NSCFString
// 2018-05-19 22:26:17.847601+0800 深浅拷贝练习[5861:566828] hello---0x6f6c6c656855----NSTaggedPointerString
// 2018-05-19 22:26:17.847619+0800 深浅拷贝练习[5861:566828] hello Objective-C---0x1005471d0----__NSCFString

集合类对象的copy和mutableCopy

集合类对象是指NSArray、NSDictionary等对象,对immutable对象进行copy,是指针拷贝,mutableCopy是进行内容拷贝。对mutable对象进行copy和mutableCopy时都是内容拷贝。但是集合对象的内容拷贝仅限于对象本身,对象元素仍然是指针拷贝。

//集合类对象的copy和mutablecopy
//1.不可变对象
NSArray *arr = @[@"",@"",@""];
NSArray *arr_copy = arr.copy;
NSMutableArray *arr_mutecopy = arr.mutableCopy;
[arr_mutecopy addObject:@""]; NSLog(@"%@----%p----%@",arr,arr,[arr class]);
NSLog(@"%@----%p----%@",arr_copy,arr_copy,[arr_copy class]);
NSLog(@"%@----%p----%@",arr_mutecopy,arr_mutecopy,[arr_mutecopy class]);
NSLog(@"\n"); // 输出
// 2018-05-19 22:34:39.850322+0800 深浅拷贝练习[5927:578661] (
// 1,
// 2,
// 3
// )----0x10070ae50----__NSArrayI
// 2018-05-19 22:34:39.850423+0800 深浅拷贝练习[5927:578661] (
// 1,
// 2,
// 3
// )----0x10070ae50----__NSArrayI
// 2018-05-19 22:34:39.850488+0800 深浅拷贝练习[5927:578661] (
// 1,
// 2,
// 3,
// 4
// )----0x10070b390----__NSArrayM //2.可变对象
NSMutableArray *arr_mute = [NSMutableArray arrayWithObjects:@"1",@"2",@"3", nil];
NSArray *arr_mute_copy = arr_mute.copy;
NSMutableArray *arr_mute_mutecopy = arr_mute.mutableCopy;
[arr_mute addObject:@"4"];
[arr_mute_mutecopy addObject:@"5"]; NSLog(@"%@----%p----%@",arr_mute,arr_mute,[arr_mute class]);
NSLog(@"%@----%p----%@",arr_mute_copy,arr_mute_copy,[arr_mute_copy class]);
NSLog(@"%@----%p----%@",arr_mute_mutecopy,arr_mute_mutecopy,[arr_mute_mutecopy class]); // 输出
// 2018-05-19 22:34:39.850556+0800 深浅拷贝练习[5927:578661] (
//                                                     1,
//                                                     2,
//                                                     3,
//                                                     4
//                                                     )----0x1031061e0----__NSArrayM
// 2018-05-19 22:34:39.850571+0800 深浅拷贝练习[5927:578661] (
//                                                     1,
//                                                     2,
//                                                     3
//                                                     )----0x1031030a0----__NSArrayI
// 2018-05-19 22:34:39.850601+0800 深浅拷贝练习[5927:578661] (
//                                                     1,
//                                                     2,
//                                                     3,
//                                                     5
//                                                     )----0x103105910----__NSArray

注意:集合类深拷贝和非集合类的深拷贝还是不太一样的,当我们对集合类进行mutableCopy操作时,虽然内存地址改变了,但是数组元素内存地址并没有发生改变,这是一个特例,也就是并不是真正意义上的完全深拷贝,也就是单层深拷贝。

深拷贝(单层深拷贝)和完全拷贝

深拷贝就是把原来对象的内容直接克隆一份到新对象里,但是这里有一个坑就是,他只会复制一层,不会复制更深层次的对象,例如:

NSArray *arr = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"one"],@"two",@"three",@"four", nil];
NSMutableString *str = arr[];
[str appendString:@"- add some data"];
NSArray *arr_copy = arr.copy;
NSMutableArray *arr_mutecopy = arr.mutableCopy; NSLog(@"%@----%p----%@----%p",arr,arr,[arr class],arr[]);
NSLog(@"%@----%p----%@----%p",arr_copy,arr_copy,[arr_copy class],arr_copy[]);
NSLog(@"%@----%p----%@----%p",arr_mutecopy,arr_mutecopy,[arr_mutecopy class],arr_mutecopy[]); // 输出
// 2018-05-19 22:57:09.819322+0800 深浅拷贝练习[6068:602956] (
// "one- add some data",
// two,
// three,
// four
// )----0x100504fb0----__NSArrayI----0x10042aaa0
// 2018-05-19 22:57:09.819514+0800 深浅拷贝练习[6068:602956] (
// "one- add some data",
// two,
// three,
// four
// )----0x100504fb0----__NSArrayI----0x10042aaa0
// 2018-05-19 22:57:09.819569+0800 深浅拷贝练习[6068:602956] (
// "one- add some data",
// two,
// three,
// four
// )----0x100506a20----__NSArrayM----0x10042aaa0

由此可知,arr_copy和arr_mutecopy对arr进行了内容拷贝,但是arr的可变字符串却没有进行内容拷贝,而是进行了单纯的浅拷贝(指针拷贝),那么arr、arr_copy和arr_mutecopy元素中第一个元素字符串是共享的,由此可以看出深拷贝并不是真正意义的完全拷贝,只是单层深拷贝。

解决办法:

归档和接档

NSArray *arr = [NSArray arrayWithObjects:[NSMutableString stringWithString:@"one"],@"two",@"three",@"four", nil];

//归档和接档的方法解决
NSMutableArray *arr_arc = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:arr]]; NSMutableString *str = arr[];
[str appendString:@"- add some data"];
NSArray *arr_copy = arr.copy;
NSMutableArray *arr_mutecopy = arr.mutableCopy; NSLog(@"%@----%p----%@----%p",arr,arr,[arr class],arr[]);
NSLog(@"%@----%p----%@----%p",arr_copy,arr_copy,[arr_copy class],arr_copy[]);
NSLog(@"%@----%p----%@----%p",arr_mutecopy,arr_mutecopy,[arr_mutecopy class],arr_mutecopy[]);
NSLog(@"%@----%p----%@----%p",arr_arc,arr_arc,[arr_arc class],arr_arc[]); // 输出
// 2018-05-19 22:57:09.819322+0800 深浅拷贝练习[6068:602956] (
// "one- add some data",
// two,
// three,
// four
// )----0x100504fb0----__NSArrayI----0x10042aaa0
// 2018-05-19 22:57:09.819514+0800 深浅拷贝练习[6068:602956] (
// "one- add some data",
// two,
// three,
// four
// )----0x100504fb0----__NSArrayI----0x10042aaa0
// 2018-05-19 22:57:09.819569+0800 深浅拷贝练习[6068:602956] (
// "one- add some data",
// two,
// three,
// four
// )----0x100506a20----__NSArrayM----0x10042aaa0
// 2018-05-20 20:54:26.698263+0800 深浅拷贝练习[6506:682670] (
// one,
// two,
// three,
// four
// )----0x100576610----__NSArrayI----0x100575e20

你真的了解iOS的深浅拷贝吗?的更多相关文章

  1. IOS开发之iOS深浅拷贝

    这里主要侧重于集合类的深浅拷贝,主要事因为工作的时候遇到这个问题. 有不足的地方欢迎指正 首先我们需要有这样的一个前提: [array addObject:obj]; 这样obj的引用计数会增加1,如 ...

  2. ios学习路线—Objective-C(深浅拷贝)

    在ObjC中,什么是深浅拷贝?  深浅拷贝分别指深拷贝和浅拷贝,即 mutableCopy 和 copy 方法.  copy复制一个不可变对象,而 mutableCopy 复制一个 mutable 可 ...

  3. @proprety数组字典字符串用copy和strong区别(深浅拷贝)

    ////  @proprety数组字典字符串用copy和strong区别(深浅拷贝).h//  IOS笔记//// /* _proprety________copy_strong_________h ...

  4. python基础(7)--深浅拷贝、函数

    1.深浅拷贝 在Python中将一个变量的值传递给另外一个变量通常有三种:赋值.浅拷贝.深拷贝 Python数据类型可氛围基本数据类型包括整型.字符串.布尔及None等,还有一种由基本数据类型作为最基 ...

  5. python day- 7 进本数据类型的先关知识点 set集合 深浅拷贝

    一.基本数据类型相关知识 1.str.    join()函数 关于字符串 a = "我爱北京" b = a.join("真的")            将&q ...

  6. 天啦噜!仅仅5张图,彻底搞懂Python中的深浅拷贝

    Python中的深浅拷贝 在讲深浅拷贝之前,我们先重温一下 is 和==的区别. 在判断对象是否相等比较的时候我们可以用is 和 == is:比较两个对象的引用是否相同,即 它们的id 是否一样 == ...

  7. Python 从零学起(纯基础) 笔记 之 深浅拷贝

    深浅拷贝 1. import  copy#浅拷贝copy.copy()#深拷贝copy.deepcopy()#赋值 = 2.   对于数字和字符串而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个 ...

  8. python——赋值与深浅拷贝

    初学编程的小伙伴都会对于深浅拷贝的用法有些疑问,今天我们就结合python变量存储的特性从内存的角度来谈一谈赋值和深浅拷贝~~~ 预备知识一——python的变量及其存储 在详细的了解python中赋 ...

  9. Python中的深浅拷贝

    1.什么是深浅拷贝? python中一切皆对象,python中的数字.字符串.元组等,如果存放在了内存中,这部分内存里面的内容是不会改变的,但是也有情况,内存中存放了可变对象,比如说列表和字典,他们的 ...

随机推荐

  1. mybatis时间范围查询

    <if test="excStartTime!=null and excStartTime!=''"> <![CDATA[ and DATE_FORMAT(dl. ...

  2. luogu 4147 玉蟾宫 悬线DP

    Code: #include<bits/stdc++.h> using namespace std; #define setIO(s) freopen(s".in",& ...

  3. Android 快速索引(城市列表和联系人)

    最近需要实现一个城市列表的快速索引功能.类似于联系人应用,根据姓名首字母快速索引功能. 要实现这个功能只需要解决两个问题:1.对列表进行分组(具有同一特征),并且能够快速定位到该组的第一项 2.右侧分 ...

  4. cookie存储userID所遇到的问题

    *)问题:control charater in cookie value or attribute 转自:https://blog.csdn.net/weixin_36380516/article/ ...

  5. 前端学习记录 week 1

    前端学习记录 week 1 基础知识 CSS盒模型 所有HTML元素可以看作盒子,在CSS中,"box model"这一术语是用来设计和布局时使用.CSS盒模型本质上是一个盒子,封 ...

  6. 北风设计模式课程---访问者(Visitor)模式

    北风设计模式课程---访问者(Visitor)模式 一.总结 一句话总结: 设计模式是日常问题的经验总结方案,所以学好设计模式对日常出现的问题可以有很好的解决. 访问者设计模式有点神似 抽象工厂模式, ...

  7. How to call javascript function on page load in asp.net

    How to call javascript function on page load in asp.net 解答1,使用RegisterStartupScript来运行 需要注意的是,下面的dem ...

  8. javascript处理json字符串

    字符串转JSON格式 var obj = JSON.parse(json字符串); 判断字段值是否存在,返回true或false obj.hasOwnProperty("error" ...

  9. django 给数据库批量添加数据

    from .models import Book import random def index(request): book_list = [] for i in range(1, 101): bo ...

  10. pthon之mock应用

    研发过程中常见分工合作开发接口,但互相之间接口有依赖,这时候便可以使用mock 目录 1.安装 2.使用mock调试自己写的方法 3.使用mock解除依赖关系 1.安装 由于我的是python2.7, ...