探究@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标识符的命名规则,即变量的命名规则: 标识符只能由字母.数字.下划线和'$'组成 数字不可以作为标识符的首字符 对象属性的命名规则 通过[]操作符为对象添加属性时,属性名称可以是任何字符串(包括只 ...
随机推荐
- SQL Server 数据加密功能解析
SQL Server 数据加密功能解析 转载自: 腾云阁 https://www.qcloud.com/community/article/194 数据加密是数据库被破解.物理介质被盗.备份被窃取的最 ...
- ASP.NET Core的路由[1]:注册URL模式与HttpHandler的映射关系
ASP.NET Core的路由是通过一个类型为RouterMiddleware的中间件来实现的.如果我们将最终处理HTTP请求的组件称为HttpHandler,那么RouterMiddleware中间 ...
- javascript表单的Ajax 提交插件的使用
Ajax 提交插件 form.js 表单的下载地址:官方网站:http://malsup.com/jquery/form/ form.js 插件有两个核心方法:ajaxForm()和ajaxSubmi ...
- python 数据类型---文件二
1.打印进度条 import sys,time for i in range(20): sys.stdout.write("#") sys.stdout.flush() #不等缓冲 ...
- 面向对象相关知识点xmind
- ActionContext.getContext().getSession()
ActionContext.getContext().getSession() 获取的是session,然后用put存入相应的值,只要在session有效状态下,这个值一直可用 ActionConte ...
- iOS之应用版本号的设置规则
版本号的格式:v<主版本号>.<副版本号>.<发布号> 版本号的初始值:v1.0.0 管理规则: 主版本号(Major version) 1. 产品的主体构件进 ...
- 超全面的.NET GDI+图形图像编程教程
本篇主题内容是.NET GDI+图形图像编程系列的教程,不要被这个滚动条吓到,为了查找方便,我没有分开写,上面加了目录了,而且很多都是源码和图片~ (*^_^*) 本人也为了学习深刻,另一方面也是为了 ...
- 用C++实现Linux中shell的ls功能
实现输出当前目录下的文件名 ls功能: 方法一: #include <iostream> #include <algorithm> #include <stdio.h&g ...
- [原创]ubuntu16.04LTS使用细节
如何给自己安装的应用创建桌面图标 拿php开发神器phpstorm为例,找到可执行文件所在路径. 这里是/home/haive/PhpStorm/bin/phpstorm.sh 打开dash,搜索&q ...