用@property声明的NSString(或NSArray,NSDictionary)经常使用copy关键字,为什么?如果改用strong关键字,可能造成什么问题?
- 因为父类指针可以指向子类对象,使用 copy 的目的是为了让本对象的属性不受外界影响,使用 copy 无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本.
- 如果我们使用是 strong ,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性.
copy 此特质所表达的所属关系与 strong 类似。然而设置方法并不保留新值,而是将其“拷贝” (copy)。 当属性类型为 NSString 时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个 NSMutableString 类的实例。这个类是 NSString 的子类,表示一种可修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变” (immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的” (mutable),就应该在设置新属性值时拷贝一份。
举例说明:
定义一个以 strong 修饰的 array:
- @property (nonatomic ,readwrite, strong) NSArray *array;
然后进行下面的操作:
- NSArray *array = @[ @1, @2, @3, @4 ];
- NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array];
- self.array = mutableArray;
- [mutableArray removeAllObjects];;
- NSLog(@"%@",self.array);
- [mutableArray addObjectsFromArray:array];
- self.array = [mutableArray copy];
- [mutableArray removeAllObjects];;
- NSLog(@"%@",self.array);
打印结果如下所示:
- 2015-09-27 19:10:32.523 CYLArrayCopyDmo[10681:713670] (
- )
- 2015-09-27 19:10:32.524 CYLArrayCopyDmo[10681:713670] (
- 1,
- 2,
- 3,
- 4
- )
(详见仓库内附录的 Demo。)
为了理解这种做法,首先要知道,两种情况:
- 对非集合类对象的 copy 与 mutableCopy 操作;
- 对集合类对象的 copy 与 mutableCopy 操作。
1. 对非集合类对象的copy操作:
在非集合类对象中:对 immutable 对象进行 copy 操作,是指针复制,mutableCopy 操作时内容复制;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。用代码简单表示如下:
- [immutableObject copy] // 浅复制
- [immutableObject mutableCopy] //深复制
- [mutableObject copy] //深复制
- [mutableObject mutableCopy] //深复制
比如以下代码:
- NSMutableString *string = [NSMutableString stringWithString:@"origin"];//copy
- NSString *stringCopy = [string copy];
查看内存,会发现 string、stringCopy 内存地址都不一样,说明此时都是做内容拷贝、深拷贝。即使你进行如下操作:
- [string appendString:@"origion!"]
stringCopy 的值也不会因此改变,但是如果不使用 copy,stringCopy 的值就会被改变。 集合类对象以此类推。 所以,
用 @property 声明 NSString、NSArray、NSDictionary 经常使用 copy 关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,他们之间可能进行赋值操作,为确保对象中的字符串值不会无意间变动,应该在设置新属性值时拷贝一份。
2、集合类对象的copy与mutableCopy
集合类对象是指 NSArray、NSDictionary、NSSet ... 之类的对象。下面先看集合类immutable对象使用 copy 和 mutableCopy 的一个例子:
- NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"]];
- NSArray *copyArray = [array copy];
- NSMutableArray *mCopyArray = [array mutableCopy];
查看内容,可以看到 copyArray 和 array 的地址是一样的,而 mCopyArray 和 array 的地址是不同的。说明 copy 操作进行了指针拷贝,mutableCopy 进行了内容拷贝。但需要强调的是:此处的内容拷贝,仅仅是拷贝 array 这个对象,array 集合内部的元素仍然是指针拷贝。这和上面的非集合 immutable 对象的拷贝还是挺相似的,那么mutable对象的拷贝会不会类似呢?我们继续往下,看 mutable 对象拷贝的例子:
- NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
- NSArray *copyArray = [array copy];
- NSMutableArray *mCopyArray = [array mutableCopy];
查看内存,如我们所料,copyArray、mCopyArray和 array 的内存地址都不一样,说明 copyArray、mCopyArray 都对 array 进行了内容拷贝。同样,我们可以得出结论:
在集合类对象中,对 immutable 对象进行 copy,是指针复制, mutableCopy 是内容复制;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。但是:集合对象的内容复制仅限于对象本身,对象元素仍然是指针复制。用代码简单表示如下:
- [immutableObject copy] // 浅复制
- [immutableObject mutableCopy] //单层深复制
- [mutableObject copy] //单层深复制
- [mutableObject mutableCopy] //单层深复制
这个代码结论和非集合类的非常相似。
总结:只有对不可变的(NSString、NSArray、NSDictionary、NSSet)进行copy 是浅复制,其他都是深复制。或者带mutable的都是深复制。
参考链接:iOS 集合的深复制与浅复制
用@property声明的NSString(或NSArray,NSDictionary)经常使用copy关键字,为什么?如果改用strong关键字,可能造成什么问题?的更多相关文章
- NSData NSDate NSString NSArray NSDictionary 相互转换
// NSData NSDate NSString NSArray NSDictionary json NSString *string = @"hello word"; NSDa ...
- 关于NSString,NSMutableString,NSArray,NSMutableArray,NSDictionary,NSMutableDictionary
NSString,NSMutableString,NSArray,NSMutableArray,NSDictionary,NSMutableDictionary 在 OC 中我们天天都要用,而我们要怎 ...
- NSData NSDate NSString NSArray NSDictionary 相互转化
// NSData NSDate NSString NSArray NSDictionary json NSString *string = @"hello word"; ...
- [转]一些NSArray,NSDictionary,NSSet相关的算法知识
iOS编程当中的几个集合类:NSArray,NSDictionary,NSSet以及对应的Mutable版本,应该所有人都用过.只是简单使用的话,相信没人会用错,但要做到高效(时间复杂度)精确(业务准 ...
- Read and Write NSArray, NSDictionary and NSSet to a File
查询地址:http://iosdevelopertips.com/data-file-management/read-and-write-nsarray-nsdictionary-and-nsset- ...
- Xcode4.4(LLVM4.0编译器)中NSArray, NSDictionary, NSNumber优化写法
Xcode4.4(LLVM4.0编译器)中NSArray, NSDictionary, NSNumber优化写法 从xcode4.4开始,LLVM4.0编译器为Objective-C添加一些新的特性. ...
- Objective-C:MRC(引用计数器)在OC内部的可变对象是适用的,不可变对象是不适用的(例如 NSString、NSArray等)
引用计数和字符串 内存中的常量字符串的空间分配与其他对象不同,他们没有引用计数机制 凡是自定义的对象都有引用计数机制: OC内部中对象分为可变对象(NSMutableString等)和不可变对象(NS ...
- 写一个 setter 方法用于完成 @property (nonatomic, retain) NSString *name,
写一个 setter 方法用于完成 @property (nonatomic, retain) NSString *name 写一个 setter 方法用于完成 @property (nonatomi ...
- NSString属性什么时候用copy,什么时候用strong?
我们在声明一个NSString属性时,对于其内存相关特性,通常有两种选择(基于ARC环境):strong与copy.那这两者有什么区别呢?什么时候该用strong,什么时候该用copy呢 ...
随机推荐
- graphql 项目搭建(二)
一.Express基本框架 1.新建一个文件夹gql-server vscode 打开项目,在终端下输入yarn init -y 生成package.json 包(如果没安装yarn ,npm也一样, ...
- 非常全面的PHP header函数设置HTTP头的示例
突然看到这个,觉得很好,就拿过来了,如下: //定义编码 header( 'Content-Type:text/html;charset=utf-8 '); //Atom header('Conten ...
- 问答 请问使用OK("raw:jpg")能返回多张图片吗
请问使用OK("raw:jpg")能返回多张图片吗 发布于 28天前 作者 qq_3aeeb0ad 78 次浏览 复制 上一个帖子 下一个帖子 标签: 无 @At( ...
- Git版本控制的原理
Git工作区域 工作目录(Working Directory) 暂存区(Stage/Index) 资源库(Repository或Git Directory) 远程的git仓库(Remote Direc ...
- 第21章 DMA—直接存储区访问—零死角玩转STM32-F429系列
第21章 DMA—直接存储区访问 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/fi ...
- javaScript校验图片大小、格式
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.or ...
- rcnn spp_net hcp
rcnn开创性工作,但是计算时间太长,重复计算太大. spp_net将重复计算避免了. hcp是yan shuicheng那边的,是用bing生成regions,然后用normalized cut将这 ...
- 基于SOA架构和流媒体技术的在线教育平台的研究
简介 现代远程教育是指通过音频.视频(直播或录像)以及包括实时和非实时在内的计算机技术把课程传送的教育.现代远程教育是随着现代信息技术的发展而产生的一种新型教育方式.计算机技术.多媒体技术.通信技术的 ...
- vue-router 实现分析
我们分别从不同的视角来看 vue-router. http://mp.weixin.qq.com/s?__biz=MzUxMzcxMzE5Ng==&mid=2247485737&idx ...
- 第一次发干货Observable.zip与Observable.forkJoin
在IT界已经混了5年了,5年中浏览了不少的网站,在上面查询自己想要的东西,解决工作中遇到的问题,心里总想有天自己能够有自己的博客,能给分享一些自己在生活中.工作中遇到的问题,让其他有类似经历的朋友能够 ...