一、问题来源

一直没有搞清楚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的原因

  1. 父类指针可以指向子类对象(如上代码中NSMutableString是NSString的子类),使用copy的目的是为了对象有更好的封装性,不受外部影响。无论外部传入可变或不可变对象,本身持有一个不可变的副本。

  2. 使用strong,属性可能指向可变对象,如果这个对象被外部更改,则该属性也会受到影响。

  3. 同样和NSString有可变子类的NSArray,NSDictionary,在声明时也应该使用copy描述。

三、对象的copy与mutablecopy

要更好的理解,我们需要搞清楚下面两种情况:

  1. 非集合对象的copy与mutablecopy

  2. 集合对象的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的区别的更多相关文章

  1. JavaScript事件对象属性e.target和this的区别

    前言: Event对象代表事件的状态,比如事件在其中发生的元素.键盘按键的状态.鼠标的位置.鼠标按钮的状态. 事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象里面,这个对象就是事件对象eve ...

  2. Vue2实践computed监听Vuex中state对象中的对象属性时发生的一些有趣经历

    今天想实现一个功能,在全局中随时改变用户的部分信息.这时候就想到了用Vuex状态控制器来存储用户信息,在页面中使用computed来监听用户这个对象.看似一个很简单的逻辑,就体现了我基本功的不扎实呀. ...

  3. JAVA存取对象属性时,如果开程多线程,记得对相关存取方法作原子化操作定义

    最显著的应用当然是银行存款和取款,不要存在存取数字和实际发生不一样的情况. synchronized关键字. class BankAccount { private int balance = 100 ...

  4. Java对象声明时:new与null的区别

    作者:林子云链接:https://www.zhihu.com/question/21468505/answer/18333632来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

  5. 实现对象属性的lazy-loading(延迟加载)

    一.延迟加载器LazyLoader作用:       说到延迟加载,应该经常接触到,尤其是使用Hibernate的时候,本篇将通过一个实例分析延迟加载的实现方式.LazyLoader接口继承了Call ...

  6. js之oop <二> 对象属性

    js中对象属性可以动态添加和删除.删除对象属性用delete关键字. function obj(){ } var oo = new obj(); oo.a = "a"; oo.b ...

  7. 创建对象的两种方法: new 和 面向对象(对象字面量)及对象属性访问方法

    创建对象的两种方法: new 和 面向对象(对象字面量)用 new 时:var o = new Object();o.name = "lin3615";alert(o.name); ...

  8. spring学习——注入静态对象属性

    spring注入静态对象属性时,因为虚拟机类加载问题,直接在属性上使用@Autowired 是不可以的.需要在属性对应的set方法上@Autowired,并且,set方法不能定义为static. 1. ...

  9. JS对象属性命名规则

    JS标识符的命名规则,即变量的命名规则: 标识符只能由字母.数字.下划线和'$'组成 数字不可以作为标识符的首字符 对象属性的命名规则 通过[]操作符为对象添加属性时,属性名称可以是任何字符串(包括只 ...

随机推荐

  1. 树莓派笔记之使用netselect选择最快Raspbian软件源

    背景: 之前在葉難大大的部落格里看到有讲可以使用netselect查找最快软件源,今天正好看到, 特此记下来,因为之前一直使用中国科学技术大学的源,结果发现不是我这里最快的. 注意: 以下仅对Rasp ...

  2. 获取浏览器信息 c#

    Request.Browser.MajorVersion.ToString();//获取客户端浏览器的版本号 Request.Browser.Version.ToString();//获取客户端浏览器 ...

  3. py替换掉换行符

    for line in file.readlines(): line=line.strip('\n')

  4. JS 内部传参

  5. php学习之路

    1.php拼接字符串+查询 $floor_id = M('house_floor_input')->where($map1)->field('id')->select(); $flo ...

  6. 解决报错:IncompleteElementException: Could not find result map...

    今天遇到这样一个报错,记录一下: org.apache.ibatis.builder.IncompleteElementException: Could not find result map com ...

  7. Codeforces 626E Simple Skewness(暴力枚举+二分)

    E. Simple Skewness time limit per test:3 seconds memory limit per test:256 megabytes input:standard ...

  8. 读取mysql数据库的数据,转为json格式

    # coding=utf-8 ''' Created on 2016-10-26 @author: Jennifer Project:读取mysql数据库的数据,转为json格式 ''' import ...

  9. magic cube

    搜索题, 每个状态能扩展出12种状态,最多进行5次旋转12^5 要用到iddfs,或者我看到网上其他人用的ida* 我也是参考了别人的代码,而且这个题vj上有点问题,我看数据看了半天,愣是没看明白第二 ...

  10. Linux 中文输入法安装

    问题一:文本不能输入中文,所以考虑到要安装搜狗输入法,在 Oracle VM VirtualBox 新建的Ubuntu系统应用中心,安装输入法总是安装失败,在自己电脑上下载了Linux的输入法文件. ...