AJ分享,必须精品

copy

copy的正目的

copy 目的:建立一个副本,彼此修改,各不干扰
Copy(不可变)和MutableCopy(可变)针对Foundation框架的数据类型。
对于自定义类,copy就是可变的。


可变数组的copy

这里用NSMutableArray为例子。

// 可变=》可变&不可变,内存地址都会变化
void copyDemo1()
{
NSMutableArray *arrayM = [NSMutableArray arrayWithObjects:@(1), @(2), nil];
NSLog(@"%@ %p %@", arrayM, arrayM, arrayM.class); // 1. 可变 => 可变
NSMutableArray *aM = [arrayM mutableCopy];
NSLog(@"%@ %p %@", aM, aM, aM.class); // 2. 可变 => 不可变
NSArray *a = [arrayM copy];
NSLog(@"%@ %p %@", a, a, a.class);
}

由结果我们得到一下结论
1:arrayM,aM,a是三个不同的对象
2:可变 => 可变 (arrayM是可变的,用mutableCopy给aM 得出aM.class是NSArrayM )
3:可变 => 不可变(aM是可变的,用copy给a 得出a.class是NSArrayI)


不可变数组的copy

void copyDemo2()
{
NSArray *array = @[@(1), @(2)];
NSLog(@"%@ %p %@", array, array, array.class); // 1. 不可变 => 可变
NSMutableArray *aM = [array mutableCopy];
NSLog(@"%@ %p %@", aM, aM, aM.class); // 2. 不可变 => 不可变(浅复制)
// 指针的复制,引用计数+1
NSArray *a = [array copy];
NSLog(@"%@ %p %@", a, a, a.class);
}

由上结果我们得到结论
1:不可变 => 可变 内存地址变了,class由NSArrayI=>NSArrayM
2:不可变 => 不可变 内存地址一致,class由NSArrayI=>NSArrayI
作用是指针的复制,引用计数+1。术语(浅复制)

3:浅复制:不可变=>不可变
深复制:其他三种情况!
(在这里记忆时候记住都不能改就是浅复制,能改就是深复制,相对于记忆四中情况更容易记忆。)

哪里用的最多呢?

这里用的最多

@property (nonatomic, copy) NSString *name;

NSString
Block

都使用copy属性,copy属性,在赋值时,会默认做一次copy操作,让他变成“不可变的类型”
strong相当于MRC中的retain,在赋值时,只是引用计数+1

在@property中使用什么杨的类型说明他,他就有什么样的方法。
例如这段代码:

 NSMutableString *strM = [NSMutableString stringWithString:@"zhangsan"];
NSLog(@"%@ %p %@", strM, strM, strM.class); Person *p = [[Person alloc] init];
p.name = strM; NSLog(@"%@ %p %@", p.name, p.name, p.name.class); // 修改"源",p.name会跟着修改
[strM setString:@"lisi"];
NSLog(@"==== %@ %p", strM, strM);
NSLog(@"%@ %p", p.name, p.name);

如果用strong来说明person的name,当我们修改strM的时候,p.name也会跟着改,如果用的时copy的话,那么他就不会被修改。这里取决于Person类中的@property
简单理解,如果用了copy就是复制一个String给name
而如果用了strong,就仅仅是引用计数+1。
p.name能不能修改呢?这里我们不能直接修改,我们需要用一个万能指针。

// 修改p.name
id obj = p.name;
[obj setString:@"wangwu"];
NSLog(@"==== %@ %p", strM, strM);
NSLog(@"%@ %p", p.name, p.name);

这要用strong能改,这样类会变得不安全。我们把strong改成copy
当我们修改“源”的时候

[strM setString:@"lisi"];

p.name还是原样的。
而这时候修改属性的方法编译没有问题,但是运行时候会报错

Attempt to mutate immutable object with xxx
视图修改一个不可变的类型,使用方法xxx

对于”可变类型”的属性,不要使用copy描述符定义,否则赋值后,就是不可变了!


copy自定义对象

[object copy]

想要让对象能用copy方法 [p copy]
(自定义对象要实现copy功能)
1> 遵守NSCopying协议(本质上就是方便程序员编写代码时候,有快捷提示)
2> 实现- (id)copyWithZone:(NSZone *)zone
(zone,区域,很少用)
所有的copy方法,最终都会调用copyWithZone方法
copy操作一个对象,复制给一个新的对象。

- (id)copyWithZone:(NSZone *)zone
{
// 1> 实例化对象,self 是对象
// self.class能够保证继承的子类同样使用copy方法
Person *p = [[self.class alloc] init]; // 2> 给属性赋值
p.name = self.name;
p.age = self.age; // 3> 返回新对象
return p;
}

这时候我们这样调用

void copyDemo5()
{
Person *p = [[Person alloc] init];
p.name = @"zhangsan";
p.age = 18; NSLog(@"%@", p); Person *p1 = [p copy];
p1.name = @"lisi";
NSLog(@"%@", p1);
}


这时候我们就能调用自己定义的类对象的copy方法了,并且可以产生一个对象。
注意:这里的p1.name = @”lisi”并不是修改,而是重新赋值。不要让copy给弄迷糊了。


2015年05月20日补充

类对象等的理解

类:是一种结构,它表示对象的类型,对象引用类来获取和本身有关的各种信息,特别是运行什么代码来处理每种操作。

对象:是一种结构,它包含值和指向其类的隐藏指针。

实例:对象的另一种称呼。

消息:是对象可以执行的操作,用于通知对象去做什么。对象接收消息后,将查询对应的类,以便查找正确的代码来运行。

方法:是为响应消息而运行的代码,根据对象的类,消息可以调用不同的方法。

接口:是对象的类应该提供特殊的特性的描述。


什么是property?

property是一种代码生成机制,能够生成不同类型的getter/setter函数,特别是如果你想要用点(.)操作符号来存取变量的话,你就能必须使用property。

如何使用property?

用法如:@property (attribute1,attribute2) float value;

这些attribute包括:

readonly 表示这个属性是只读的,就是只生成getter方法,不会生成setter方法。

readwrite 可读可写(默认)设置可访问级别。

assign:简单赋值,不更改索引计数

copy:建立一个索引数为1的对象,然后释放旧对象

retain:释放(release)旧对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1

nonatomicnonatomic 非原子性访问,不加同步,多线程并发访问会提高性能。注意,如果不加此属性,
则默认是两个访问方法都为原子型事务访问。

前两个只是简单的设定变量的可读写性。

详细解释:copy其实是建立了一个相同的对象,而retain不是:

比如一个NSString对象,地址为0x1111,内容为@”cat” ,copy到另外一个NSString之后,地址为0x2222,内容相同,新的对象retain为1,旧有对象没有变化。

retain 到另一个NSString之后,地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1,也就是说,retain是指针拷贝,copy是内容拷贝。在拷贝之前,都会释放旧的对象。

assign:简单赋值,不更改索引计数(Reference Counting)。

copy:建立一个索引计数为1的对象,然后释放旧对象

retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的输入对象的索引计数为1

使用assign:对基础数据类型(NSInteger)和C数据类型(int ,float,double,char等)

使用copy:对NSString

使用retain:对其他NSObject和其子类。

最新文章

  1. Lesson 10 Not for jazz
  2. 相克军_Oracle体系_随堂笔记002-基础
  3. css-css权威指南学习笔记5
  4. 使用CTE减少统计子查询
  5. easyUI 后台经典框架DEMO下载
  6. AC日记——单词翻转 1.7 27
  7. 纯CSS实现tooltip提示框,CSS箭头及形状
  8. 以守护进程方式启动firefly
  9. ide编码害死人
  10. SaberRD之直流工作点分析
  11. webpack务虚扫盲
  12. js备战春招の四のdevtool中各种错误、调试的使用技巧
  13. 【Android Studio安装部署系列】目录
  14. list set map区别及适用场景
  15. data_type
  16. spark on yarn任务提交缓慢解决
  17. OnSen UI结合AngularJs打造”美团"APP首页 --Hybrid Ap
  18. 【LOJ】#2077. 「JSOI2016」飞机调度
  19. debian7编译安装tengine添加lua和ldap模块
  20. Git 学习(七)标签管理

热门文章

  1. 华为云+NextCloud(私人云盘搭建)
  2. 手动实现AJAX
  3. 如何获取主键返回值(MySQL、Oracle)
  4. Go语言库系列之dotsql
  5. PHP一致性hash
  6. Rust入坑指南:居安思危
  7. 【NLP面试QA】基本策略
  8. Python python 函数参数:必选参数,默认参数
  9. [noip模拟]心<并查集>
  10. Java 判断 循环