探究@property申明对象属性时copy与strong的区别
一、问题来源

一直没有搞清楚NSString、NSArray、NSDictionary……属性描述关键字copy和strong的区别,看别人的项目中属性定义有的用copy,有的用strong。自己在开发中也是没有认真的去研究,至于使用copy还是用strong完全是根据心情随性而为,也一直没有出什么问题。可苹果竟然分了两个关键字,就肯定有其用意,为了提高自己还是要仔细的搞清楚其中之差别!好了,废话说完进入正题。
二、对象属性描述copy与strong的区别
直接上代码:
```
@property(nonatomic,strong) NSString strongImmutableString;
@property(nonatomic,copy) NSString copyImmutableString;
NSMutableString *mutableStr = [NSMutableString stringWithString:@"BUSYLIFE"];
self.immutableStrongStr = mutableStr;
self.immutableCopyStr = mutableStr;
NSLog(@"StrongStr:%@",_immutableStrongStr);
NSLog(@"CopyStr:%@",_immutableCopyStr);
[mutableStr appendString:@"1987"];
NSLog(@"mutableStr:%@",mutableStr);
NSLog(@"ChangedStrongStr:%@",_immutableStrongStr);
NSLog(@"ChangedCopyStr:%@",_immutableCopyStr);
NSLog(@"StrongStrAddress:%p",_immutableStrongStr);
NSLog(@"CopyStrAddress:%p",_immutableCopyStr);
NSLog(@"mutableStrAddress:%p",mutableStr);
```
结果如下:

上面代码中我们将字符串属性指向可变的字符串,当改变可变对象内容时,strong描述的属性会跟着改变,copy描述的属性则不会,从打印结果中可以看到strongImmutableString和可变对象mutableStr的地址是一样的,而copyImmutableStr不是。
结论
为什么我们在用@property声明NSString是经常要使用copy而不是strong的原因
父类指针可以指向子类对象(如上代码中NSMutableString是NSString的子类),使用copy的目的是为了对象有更好的封装性,不受外部影响。无论外部传入可变或不可变对象,本身持有一个不可变的副本。
使用strong,属性可能指向可变对象,如果这个对象被外部更改,则该属性也会受到影响。
同样和NSString有可变子类的NSArray,NSDictionary,在声明时也应该使用copy描述。
三、对象的copy与mutablecopy
要更好的理解,我们需要搞清楚下面两种情况:
非集合对象的copy与mutablecopy
集合对象的copy与mutablecopy
在非集合类对象中:对 immutable(不可变) 对象进行 copy 操作,是指针复制,mutableCopy 操作时内容复制;对 mutable(可变) 对象进行 copy 和 mutableCopy 都是内容复制。用代码简单表示如下:
- [immutableObject copy] // 浅复制
- [immutableObject mutableCopy] //深复制
- [mutableObject copy] //深复制
- [mutableObject mutableCopy] //深复制
集合类对象是指 NSArray、NSDictionary、NSSet ... 之类的对象。下面先看集合类immutable对象使用 copy 和 mutableCopy 的一个例子:
NSArray *array = @[@"a", @"b"];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
查看内容,可以看到 copyArray 和 array 的地址是一样的,而 mCopyArray 和 array 的地址是不同的。说明 copy 操作进行了指针拷贝,mutableCopy 进行了内容拷贝。但需要强调的是:此处的内容拷贝,仅仅是拷贝 array 这个对象,array 集合内部的元素仍然是指针拷贝。
- [immutableObject copy] // 浅复制
- [immutableObject mutableCopy] //单层深复制
- [mutableObject copy] //单层深复制
- [mutableObject mutableCopy] //单层深复制
理解了这两种操作,就可以很容易的明白上面property声明NSString时用copy到底发生了什么以及他的作用了。

本文若有不对之处,欢迎大家拍砖!
最后做个小广告,前段时间写了一个抓包程序,从各大网站抓取了一些相关旅游、摄影、深度关注等领域的数据,免得浪费就维护了一个公众号。其实主要是因为我很喜欢旅游,闲暇时喜欢看看别人的旅游故事,毕竟世界那么大,我却没有足够的时间去看看,主要还是没有足够物质基础,不过看看别人的旅游也可以有很多的想象与感悟吧。也算是一种自我激励,”这个地方将来我一定也要去看看“,加油吧!!!
有和我一样爱好,也在为生活而努力拼搏的小伙伴,可以关注一下。

探究@property申明对象属性时copy与strong的区别的更多相关文章
- JavaScript事件对象属性e.target和this的区别
前言: Event对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态. 事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象eve ...
- Vue2实践computed监听Vuex中state对象中的对象属性时发生的一些有趣经历
今天想实现一个功能,在全局中随时改变用户的部分信息.这时候就想到了用Vuex状态控制器来存储用户信息,在页面中使用computed来监听用户这个对象.看似一个很简单的逻辑,就体现了我基本功的不扎实呀. ...
- JAVA存取对象属性时,如果开程多线程,记得对相关存取方法作原子化操作定义
最显著的应用当然是银行存款和取款,不要存在存取数字和实际发生不一样的情况. synchronized关键字. class BankAccount { private int balance = 100 ...
- Java对象声明时:new与null的区别
作者:林子云链接:https://www.zhihu.com/question/21468505/answer/18333632来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- 实现对象属性的lazy-loading(延迟加载)
一.延迟加载器LazyLoader作用: 说到延迟加载,应该经常接触到,尤其是使用Hibernate的时候,本篇将通过一个实例分析延迟加载的实现方式.LazyLoader接口继承了Call ...
- js之oop <二> 对象属性
js中对象属性可以动态添加和删除.删除对象属性用delete关键字. function obj(){ } var oo = new obj(); oo.a = "a"; oo.b ...
- 创建对象的两种方法: new 和 面向对象(对象字面量)及对象属性访问方法
创建对象的两种方法: new 和 面向对象(对象字面量)用 new 时:var o = new Object();o.name = "lin3615";alert(o.name); ...
- spring学习——注入静态对象属性
spring注入静态对象属性时,因为虚拟机类加载问题,直接在属性上使用@Autowired 是不可以的.需要在属性对应的set方法上@Autowired,并且,set方法不能定义为static. 1. ...
- JS对象属性命名规则
JS标识符的命名规则,即变量的命名规则: 标识符只能由字母.数字.下划线和'$'组成 数字不可以作为标识符的首字符 对象属性的命名规则 通过[]操作符为对象添加属性时,属性名称可以是任何字符串(包括只 ...
随机推荐
- 【.net 深呼吸】细说CodeDom(4):类型定义
上一篇文章中说了命名空间,你猜猜接下来该说啥.是了,命名空间下面就是类型,知道了如何生成命名空间的定义代码,之后就该学会如何声明类型了. CLR的类型通常有这么几种:类.接口.结构.枚举.委托.是这么 ...
- [.NET] C# 知识回顾 - 事件入门
C# 知识回顾 - 事件入门 [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/6057301.html 序 之前通过<C# 知识回顾 - 委托 de ...
- javascript工厂模式和构造函数模式创建对象
一.工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程(本书后面还将讨论其他设计模式及其在JavaScript 中的实现).考虑到在ECMAScript 中无法创 ...
- DDD 领域驱动设计-谈谈 Repository、IUnitOfWork 和 IDbContext 的实践(3)
上一篇:<DDD 领域驱动设计-谈谈 Repository.IUnitOfWork 和 IDbContext 的实践(2)> 这篇文章主要是对 DDD.Sample 框架增加 Transa ...
- 免费开源的.NET多类型文件解压缩组件SharpZipLib(.NET组件介绍之七)
前面介绍了六种.NET组件,其中有一种组件是写文件的压缩和解压,现在介绍另一种文件的解压缩组件SharpZipLib.在这个组件介绍系列中,只为简单的介绍组件的背景和简单的应用,读者在阅读时可以结合官 ...
- [原] KVM 虚拟化原理探究(2)— QEMU启动过程
KVM 虚拟化原理探究- QEMU启动过程 标签(空格分隔): KVM [TOC] 虚拟机启动过程 第一步,获取到kvm句柄 kvmfd = open("/dev/kvm", O_ ...
- [EasyUI美化换肤]更换EasyUi图标
前言 本篇文章主要是记录一些换EasyUI皮肤的过程,备忘.也欢迎美工大神各路UI给点好意见,EasyUI我就不介绍了,自行百度吧..(So..所以别问我是不是响应式..本身EasyUI就不是响应式. ...
- 基于window7+caffe实现图像艺术风格转换style-transfer
这个是在去年微博里面非常流行的,在git_hub上的代码是https://github.com/fzliu/style-transfer 比如这是梵高的画 这是你自己的照片 然后你想生成这样 怎么实现 ...
- C 盘的不速之客
C 盘的报告内容既然上GB的空间 操作系统版本 原来是微软这个查找解决异常关闭解决方案生成的报告 参考 How To Disable Vista Error Reporting Feature ...
- 如何获取url中的参数并传递给iframe中的报表
在使用报表软件时,用户系统左边一般有目录树,点击报表节点就会在右侧网页的iframe中显示出报表,同时点击的时候也会传递一些参数给网页,比如时间和用户信息等.如何使网页中的报表能够获取到传递过来的参数 ...