小结 iOS 中的 copy
预备知识 :
内存的栈区 : 由编译器自动分配释放, 存放函数的参数值, 局部变量的值等. 其 操作方式类似于数据结构中的栈.
内存的堆区 : 一般由程序员分配释放, 若程序员不释放, 程序结束时可能由OS回 收. 注意它与数据结构中的堆是两回事, 分配方式倒是类似于链表.
copy方法和mutableCopy方法
如果你想要创建一个对象, 该对象与源对象的内容一致, 那么你可以考虑用拷贝(copy或mutableCopy), 首先, 我将会利用字符串, 数组, 字典这三种常见的对象来说明copy与mutableCopy的区别.
NSString
NSString *string = @"Jerry";
[string copy] --> 拷贝出内容为Jerry的NSString类型的字符串
[string mutableCopy] --> 拷贝出内容为Jerry的NSMutableString类型的字符串
NSDictionary
NSDictionary *dict = @{@"name" : @"Jerry"};
[dict copy] --> 拷贝出内容与dict相同的NSDictionary类型的字典
[dict mutableCopy] --> 拷贝出内容与dict相同的NSMutableDictionary类型的字典
NSArray
NSArray *array = @[@"Jerry"];
[array copy] --> 拷贝出内容与array相同的NSArray类型的数组
[array mutableCopy] --> 拷贝出内容与array相同的NSMutableArray类型的数组
总结
copy拷贝出来的对象类型总是不可变类型(例如, NSString, NSDictionary, NSArray等等)
mutableCopy拷贝出来的对象类型总是可变类型(例如, NSMutableString, NSMutableDictionary, NSMutableArray等等)
深拷贝与浅拷贝
何为深拷贝, 何为浅拷贝?
深拷贝 : 拷贝出来的对象与源对象地址不一致! 这意味着我修改拷贝对象的值对源对象的值没有任何影响.
浅拷贝 : 拷贝出来的对象与源对象地址一致! 这意味着我修改拷贝对象的值会直接影响到源对象.
这里需要纠正网上一些错误的观点(以下为错误观点)
copy都是浅拷贝, mutableCopy都是深拷贝
我们知道, 当我们用copy从一个可变对象拷贝出一个不可变对象时, 这种情况就属于深拷贝而不是浅拷贝!!
注意 ! 深拷贝与浅拷贝也有相对之分!!!看下面
对于NSString对象, 确实深拷贝就是深拷贝, 浅拷贝就是浅拷贝, 没有任何异议.
但是对于NSArray, NSDictionary, NSSet这些容器类的对象呢? 当然浅拷贝依然是指针拷贝, 那深拷贝意味着连同容器及其容器内的对象一并拷贝吗? 还是只拷贝容器对象, 对容器内的对象则只是简单引用呢? 这里有两种情况, 我姑且把它称为不完全深拷贝与完全深拷贝
不完全深拷贝
不完全深拷贝就是只拷贝容器对象(拷贝一个壳), 而对于容易内的对象则只保存一份引用.
所以我们知道, 就算我们修改copyArray不会影响到源array, 但是我通过copyArray修改数组内的object, 对应地源array内的object也会随之修改, 大家可以自行测试.
完全深拷贝
完全深拷贝就是连同容器内的对象在内, 完完全全拷贝一份出来
通过图片可以很清楚地知道, 这种情况下无论是修改copyArray还是通过copyArray修改数组内的object, 对源array都不会造成半点影响.
ps : 默认状态下深拷贝指的是不完全深拷贝, 如要实现完全深拷贝, 则要重写copyWithZone: 方法, 自行实现完全深拷贝的需求. 大体思路如下, 在copyWithZone: 里对象赋值上不直接赋值而是通过copy方法即可实现, 这里不作具体讨论.
block为什么要用copy?
首先, block是一个对象, 所以block理论上是可以retain/release的. 但是block在创建的时候它的内存是默认是分配在栈(stack)上, 而不是堆(heap)上的. 所以它的作用域仅限创建时候的当前上下文(函数, 方法…), 当你在该作用域外调用该block时, 程序就会崩溃.
意思就是 : 一般情况下你不需要自行调用copy或者retain一个block. 只有当你需要在block定义域以外的地方使用时才需要copy. Copy将block从内存栈区移到堆区.
其实block使用copy是MRC留下来的也算是一个传统吧, 在MRC下, 如上述, 在方法中的block创建在栈区, 使用copy就能把他放到堆区, 这样在作用域外调用该block程序就不会崩溃. 但在ARC下, 使用copy与strong其实都一样, 因为block的retain就是用copy来实现的, 所以block使用copy还能装装逼, 说明自己是从MRC下走过来的..嘿嘿
copy相对于直接赋值的好处
看看以下代码 :
大家猜猜控制台输出是啥? 是( Kobe ), ( Kobe, McGrady )吗?
错了错了!!!
array = ( Kobe, McGragy), mArray = ( Kobe, McGragy)
为什么??? 明明可变数组添加对象是在赋值之后, 为什么后面添加对象还会影响到不可变数组呢??
原因很简单, 因为Objective-C支持多态.
所以表面上self.array是NSArray对象, 其实骨子里是NSMutableArray对象.这样的话将会对后期DEBUG增加很大的成本, 可能会导致莫名其妙的错误.
再看以下代码 :
大家再来猜一下输出会是什么?
没错!
array = ( Kobe), mArray = ( Kobe, McGragy)
这样就能保证不管赋值的是可变还是不可变数组, NSArray就是NSArray了!(你爸就是你爸, 不可能变成你了)
所以大家现在知道为什么@property中的NSString, NSArray, NSDictionary属性为什么大多时候用copy而不用strong的原因了么?
总结
这里做出了一张图, 帮助新手弄清楚copy与mutableCopy的区别, 大神请无视^_^
如果能够在你的工程中正确使用copy, 将会对你的程序有不小的帮助.细节决定成败嘛!!
小结 iOS 中的 copy的更多相关文章
- iOS中的copy
原文:http://www.jianshu.com/p/5254f1277dba 内存的栈区 : 由编译器自动分配释放, 存放函数的参数值, 局部变量的值等. 其操作方式类似于数据结构中的栈. 内存的 ...
- iOS中assign、copy 、retain等关键字的含义
iOS中assign.copy .retain等关键字的含义 转自:http://my.oschina.net/majiage/blog/267409 assign: 简单赋值,不更改索引计数cop ...
- iOS中GCD的使用小结
http://www.jianshu.com/p/ae786a4cf3b1 本篇博客共分以下几个模块来介绍GCD的相关内容: 多线程相关概念 多线程编程技术的优缺点比较? GCD中的三种队列类型 Th ...
- iOS中copy和strong修饰符的区别
iOS中copy和strong修饰符的区别 //用copys修饰的生成的都是不可变的对象 ,如果调用可变类型方法的直接报错 @property(nonatomic,copy)NSString * cp ...
- iOS中多控制器的使用
通常情况下,一个app由多个控制器组成,当app中有多个控制器的时候,我们就需要对这些控制器进行管理. 在开发过程中,当有多个View时,可以用一个大的view去管理多个小的view,控制器也是如此, ...
- iOS中消息的传递机制
本文中,会经常提及接收者[recipient]和发送者[sender].在消息传递机制中具体是什么意思,我们可以通过一个示例来解释:一个table view是发送者,而它的delegate就是接收者. ...
- iOS中的数据持久化方式
iOS中的数据持久化方式,基本上有以下四种:属性列表.对象归档.SQLite3和Core Data. 1.属性列表 涉及到的主要类:NSUserDefaults,一般 [NSUserDefaults ...
- iOS:iOS中的多控制器管理
iOS中的控制器有三种创建方式: 1.通过storyboard创建 UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@" ...
- IOS中的Block与C++11中的lambda
ios中的block 可以说是一种函数指针,但更确切的讲,其实际上其应该算是object-c对C++11中lambda的支持或者说是一个语言上的变体,其实际内容是一样的,C++的lambda我已经有简 ...
随机推荐
- WPF之Treeview控件简单用法
TreeView:表示显示在树结构中分层数据具有项目可展开和折叠的控件 TreeView 的内容是可以包含丰富内容的 TreeViewItem 控件,如 Button 和 Image 控件.TreeV ...
- 简单学C——第七天
函数 函数是C语言重要的组成部分,你现在,或者以后(如果C没什么变化的话)所写的任何一个C语言程序都是由一个一个的函数组合在一起的,当然,现在或许你只会在主函数 main中写一个小程序,那么在看了本篇 ...
- bzoj 1034: [ZJOI2008]泡泡堂BNB 貪心
1034: [ZJOI2008]泡泡堂BNB Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1398 Solved: 727[Submit][Sta ...
- Nodejs异步
http://cnodejs.org/topic/4f16442ccae1f4aa2700113b http://cnodejs.org/topic/4f16442ccae1f4aa27001123 ...
- NOR FLASH与NAND FLASH
整理自NOR FLASH 与NAND FLASH 1:NandFlash与NorFlash典型电路图 Nor Flash接原理图 从上图可以看出,该NorFlash采用并行地址和数据总线, 其中,21 ...
- SQL SELECT基本语句结构
(1)SELECT select_list (2) FROM table_list (3) WHERE search_conditions GROUP BY group_by_list ...
- Chrome测试网站加载时间与流量消耗
加载10M内容,耗时近10秒钟 大概页面图片下载时,同时进行了,有的大图,下载要几秒钟
- [LeetCode#128]Word Ladder II
Problem: Given two words (start and end), and a dictionary, find all shortest transformation sequenc ...
- bzoj1014
动态询问LCP,所以我们不好用后缀数组考虑使用维护序列问题的splay+hash求LCP这里mark一下,hash求LCP常用mo=9875321自然溢出的话交上去莫名其妙WA了这里树上某节点hash ...
- WordPress wp-admin/includes/post.php脚本安全漏洞
漏洞名称: WordPress wp-admin/includes/post.php脚本安全漏洞 CNNVD编号: CNNVD-201309-168 发布时间: 2013-09-13 更新时间: 20 ...