AJ分享,必须精品

copy

copy的正目的

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


可变数组的copy

这里用NSMutableArray为例子。

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

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


不可变数组的copy

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

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

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

哪里用的最多呢?

这里用的最多

  1. @property (nonatomic, copy) NSString *name;

NSString
Block

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

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

  1. NSMutableString *strM = [NSMutableString stringWithString:@"zhangsan"];
  2. NSLog(@"%@ %p %@", strM, strM, strM.class);
  3. Person *p = [[Person alloc] init];
  4. p.name = strM;
  5. NSLog(@"%@ %p %@", p.name, p.name, p.name.class);
  6. // 修改"源",p.name会跟着修改
  7. [strM setString:@"lisi"];
  8. NSLog(@"==== %@ %p", strM, strM);
  9. NSLog(@"%@ %p", p.name, p.name);

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

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

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

  1. [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操作一个对象,复制给一个新的对象。

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

这时候我们这样调用

  1. void copyDemo5()
  2. {
  3. Person *p = [[Person alloc] init];
  4. p.name = @"zhangsan";
  5. p.age = 18;
  6. NSLog(@"%@", p);
  7. Person *p1 = [p copy];
  8. p1.name = @"lisi";
  9. NSLog(@"%@", p1);
  10. }


这时候我们就能调用自己定义的类对象的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和其子类。

AJ整理问题之:copy,对象自定义copy 什么是property的更多相关文章

  1. 自定义对象实现copy,遵守协议<NSCopying, NSMutableCopying>

    自定义对象实现copy,步骤 1.需要遵守NSCopying协议 2.实现协议中的- (id)copyWithZone:(NSZone *)zone 3.在- (id)copyWithZone:(NS ...

  2. 对象的copy

    一般来讲,java中,对象的copy一般是通过Beans.copy(B, A);用来将A对象复制给B对象,包括对象里面的属性和值. 但但但...... 这样做,有一个很严重的问题,那就是:如果把A对象 ...

  3. BeanUtils对象属性copy的性能对比以及源码分析

    1. 对象属性拷贝的常见方式及其性能 在日常编码中,经常会遇到DO.DTO对象之间的转换,如果对象本身的属性比较少的时候,那么我们采用硬编码手工setter也还ok,但如果对象的属性比较多的情况下,手 ...

  4. Objective-C 谈谈深浅拷贝,copy和mutable copy都不是完全拷贝

    (一)字符串中的指针赋值,copy和mutablecopy NSString和NSString (1)指针赋值 肯定指向同一个字符串地址. (2)copy(和直接指向一样) NSString *str ...

  5. python deep copy and shallow copy

    Python中对于对象的赋值都是引用,而不是拷贝对象(Assignment statements in Python do not copy objects, they create bindings ...

  6. 【ObjectC—浅copy和深copy】

    一.OC设计copy的目的 为了能够从源对象copy一个新的对象副本,改变新对象(副本)的时候,不会影响到原来的对象. 二.实现copy协议 OC提供了两种copy方法:copy和mutableCop ...

  7. [CareerCup] 13.4 Depp Copy and Shallow Copy 深拷贝和浅拷贝

    13.4 What is the difference between deep copy and shallow copy? Explain how you would use each. 这道题问 ...

  8. (五)聊一聊深Copy与浅Copy

    一.关于浅copy与深copy 首先说明一下: 在python中,赋值其实就是对象的引用,变量就是对象的一个标签,如果把内存对象比喻成一个个房间,那么变量就是门牌号. 深copy与浅copy只是针对可 ...

  9. java深copy (伪深copy)【原】

    Teacher.java package test.clone; /** * 老师 * 深copy需要实现Cloneable接口 * @author King * */ public class Te ...

随机推荐

  1. Jsp el表达式无解析 解决

    需要开启 el isELIgnored="false" 这时已经可以正常访问了  

  2. Spring Controller单例与线程安全那些事儿

    目录 单例(siingleton)作用域 原型(Prototype)作用域 多个HTTP请求在Spring控制器内部串行还是并行执行方法? 实现单例模式并模拟大量并发请求,验证线程安全 附录:Spri ...

  3. 用c写的简单的日历(学习模块划分)

    简单日历 ​ 主要目的是学习函数模块划分,成品大概是这样,加了一些花里胡哨的东西(/▽\) ​ 分三个模块,主函数.c 显示.c 计算.c 与.h 文件 有两种实现方式,区别在于是否以数组在模块之间传 ...

  4. Unity 随机房间地图生成

    无论是在迷宫还是类似于地牢的游戏地图中,利用程序来生成每次都不一样的地图是一件叫人兴奋不已的事. 这时我们需要解决两个非常重要的随机事件: 1.在一定范围内随机出各不相同但又不能互相重叠的房间 2.优 ...

  5. OpenCV-Python 轮廓:入门 | 二十一

    目标 了解轮廓是什么. 学习查找轮廓,绘制轮廓等. 你将看到以下功能:cv.findContours(),cv.drawContours() 什么是轮廓? 轮廓可以简单地解释为连接具有相同颜色或强度的 ...

  6. 【干货】史上最全的Tensorflow学习资源汇总

    欢迎大家关注我们的网站和系列教程:http://www.tensorflownews.com/,学习更多的机器学习.深度学习的知识! 作者:AI小昕 在之前的Tensorflow系列文章中,我们教大家 ...

  7. Redis启动出现creating server tcp listening socket错误

    错误如图所示 解决方法 在命令行中运行 redis-cli.exe 127.0.0.1:6379>shutdown not connected>exit 然后重新运行redis-serve ...

  8. [noip模拟]改造二叉树<LIS>

    1.改造二叉树 [题目描述] 小Y在学树论时看到了有关二叉树的介绍:在计算机科学中,二叉树是每个结点最多有两个子结点的有序树.通常子结点被称作“左孩子”和“右孩子”.二叉树被用作二叉搜索树和二叉堆.随 ...

  9. 纯html加css的键盘UI效果图

    先上效果图: 没有打字的功能,纯属是个界面图(一时无聊写的) 代码如下: <!DOCTYPE html> <html> <head> <meta charse ...

  10. 实战级Stand-Alone Self-Attention in CV,快加入到你的trick包吧 | NeurIPS 2019

    论文提出stand-alone self-attention layer,并且构建了full attention model,验证了content-based的相互关系能够作为视觉模型特征提取的主要基 ...