IOS — Copy

Copy

主要内容:

  • copy的基本使用
  • 自定义对象的copy属性
  • 支持copy的自定义对象

1. copy的基本使用

♠ copy的效果:

  对源对象进行copy,建立出新的副本,彼此修改互不干扰!

♠ OC中有两种copy方式

  1> copy

    如果对象有可变/不可变之分,copy只能copy出不可变版本,如果没有此区分,copy方法就是建立一个副本。

  2> mutableCopy

    建立对象的可变副本(仅仅是当对象有可变和不可变版本时才需要是要本方法)

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self copyDemo1];
    NSLog(@"------------------");
    [self copyDemo2];
}

- (void)copyDemo1{
    NSString *str1 = @"copy1";
    NSLog(@"%@ %p",[str1 class],str1);
    // copy   => 不可变  不产生新对象 相当于引用计数器+1
    id  obj = [str1 copy];
    NSLog(@"%@ %p",[obj class],obj);
    // mutableCopy  => 可变  产生新对象
    id obj2 = [str1 mutableCopy];
    NSLog(@"%@ %p",[obj2 class],obj2);
}

- (void)copyDemo2{
    NSMutableString *str2 = [NSMutableString stringWithString:@"copy2"];
    NSLog(@"%@ %p",[str2 class],str2);
    // copy   => 不可变 产生新对象
    id obj1 = [str2 copy];
    NSLog(@"%@ %p",[obj1 class],obj1);
    // mutableCopy  => 可变,产生新对象
    id obj2 = [str2 mutableCopy];
    NSLog(@"%@ %p",[obj2 class],obj2);

}
@end

♠ 小结:

  可变    ---> 不可变

  可变    ---> 可变

  不可变 ---> 可变                      以上3种都会产生新的对象(深拷贝)

  不可变 ---> 不可变                   不会产生新对象,仅仅是对计数器+1(浅拷贝)



2. 自定义对象的copy属性

♠ 当一个对象的NSString类型属性使用strong 修饰

@property (nonatomic,strong) NSString *name;

如果对该属性做如下设置

person *p = [[person alloc]init];

    NSMutableString *str = [NSMutableString stringWithString:@"aaaa"];

    p.name = str;

    NSLog(@"%@",[p.name class]);   // 输出结果:__NSCFString

    [str setString:@"bbbb"];

    NSLog(@"%@",[p.name class]);   // 输出结果:__NSCFString

从打印输出可以发现:

p.name属性的类型已经变为NSMutableString类型,而与我们当初定义的类型不一致,为什么?

  因为一个对象的准确类型是在给改对象“分配内存空间”的时候制定的类型,而程序员指定属性为某对象的类型之后就可以具有该对象的方法,而能否运行成功取决于该属性的实际类型,如果使用了实际类型不存在的方法,将会报"unrecognized selector send to instance"

例如:

    id aa  = [[NSObject alloc]init];

    NSString *string = aa;

    NSLog(@"%zd",string.length);

  此代码块中,定义了NSString类型的变量,试图指向了NSObject的对象,当调用NSString的length方法时,编译可以通过,但是由于string的实际类型是NSObject类型,并不存在该方法,所有会报方法不存在错误:

unrecognized selector sent to instance 0x7f9628c8b7f0‘

发现问题:

  当我们使用strong修饰成员属性时,将会有多个指针指向相同的对象,并可对其进行操作,而在程序设计过程中,有些时候我们的操作并不希望影响源数据,此时可能就需要改变变量的修饰为copy

♠ 面向对象程序开发中,有一个非常重要的原则

开闭原则:

  - 开:对内开放,想怎么改,就怎么改

  - 闭:对外封闭,只能用,不能改

定义成copy的属性,在设置时会默认进行一次copy操作;

  -> 对可变属性进行copy ———— 新建副本

  -> 对不可变属性进行copy ———— 不会创建新的对象,只是计数器+1,跟strong类型一致的。

使用注意:

  对于有可变与不可变之分类型的属性而言,由于copy操作得到的将是不可变类型,所有对于可变类型的属性,不应该使用copy去修饰。



3. 支持copy的自定义对象

先来看程序,有自定义类,有两个成员属性

@property (nonatomic,copy)NSString *name;
@property (nonatomic,assign) int age;

控制器中实例化对象,并尝试使用copy

person *p1 = [[person alloc] init];
    p1.name = @"aaa";
    p1.age  = 12;

    person *p2 = [p1 copy];
    p2.name = @"bbb";
    p2.age  = 14;

运行可发现:

-[person copyWithZone:] 系统将提示没有实现copyWithZone方法;

那么问题来了,copyWithZone:与copy方法有什么关系?

苹果官方文档中描述:

Returns the object returned by copyWithZone:,

This is a convenience method for classes that adopt the NSCopyingprotocol. An exception is raised if there is no implementation for copyWithZone:.

NSObject does not itself support the NSCopyingprotocol. Subclasses must support the protocol and implement the copyWithZone: method. A subclass version of the copyWithZone: method should send the message to super first, to incorporate its implementation, unless the subclass descends directly from NSObject.

我们可以从中得到一些信息:
1> copy 是 copyWithZone的简化形式,如果没有实现copyWithZone方法而调用copy会出现异常;

2> NSObject 类本身并没有遵守NSCopying协议,子类想要使用copy方法,必须遵守协议,并且实现copyWithZone方法;

3> 子类实现copyWithZone:方法必须先调用父类的copyWithZone,除非子类直接继承于NSObject

也就是说若要是的我们自定义类能够拷贝,有两个条件:

  * 类遵守NSCopying协议

  * 类实现copyWithZone:方法

      Zone: 分配对象是需要内存空间的,如果指定了zone,就可以指定新对象的内存空间,但是zone是一个非常古老的技术,为避免在堆中出现碎片而使用的,如今已几乎不用。

- (id)copyWithZone:(NSZone *)zone{
    person *p = [[self.class alloc]init];
    p.name = self.name;
    p.age  = self.age;

    return p;
}

self.class 的原因:

  1> copyWithZone: 是一个对象方法,self.class 获得类对象

  2> 保证创建的对象都是person类或者子类对象

如果父类也实现了copyWithZone:方法,必须调用父类copyWithZone:方法。



IOS — Copy

时间: 2024-10-06 13:12:56

IOS — Copy的相关文章

ios copy 和 retain 字符串

1 @property (retain, nonatomic) NSString *retainStr; 2 @property (copy, nonatomic) NSString *copyStr; 3 4 5 6 @property (retain, nonatomic) NSMutableString *retainMStr; 7 @property (copy, nonatomic) NSMutableString *copyMStr; 8 9 10 11 实现代码如下: 12 13

iOS -copy&mutableCopy

1.对于非容器对象(NSString) 不可变 (NSString) copy :浅复制,指针指向 mutableCopy:深复制,生成可变字符串对象 可变(NSMutableString) copy: 深复制,生成不可变字符串对象 mutableCopy :深复制,生成可变字符串对象 2.对于容器类对象 数组 不可变(NSArray) copy :浅复制,指针指向 mutableCopy:深复制,生成可变数组对象(但,数组中的对象没有进行处理的话,数组的中的对象是浅复制) 可变(NSMutab

iOS copy 和 mutableCopy 学习

(参考 iOS 52个技巧学习心得笔记 第二章 对象 , 消息, 运行期)的对象部分 关于Copy  有个经典问题”大部分的时候NSString的属性都是copy,那copy与strong的情况下到底有什么区别呢” 或者说”为什么 NSString 类型成员变量的修饰属性用 copy 而不是 strong (或 retain ) ?” 明显 第一句比第二句 严谨多了. @property (strong,nonatomic) NSString *strongString; & @property

iOS copy/retain/assign

1 深复制:内容拷贝,源对象和副本对象指的是两个不同的对象,源对象引用计数器不变,副本对象引用计数器为1 2 浅复制:指针拷贝,源对象和副本对象指的都是同一个对象,对象引用计数器+1,相当于retain 3 只有不可变对象创建不可变副本(copy)才是浅复制,其它的都是深复制 copy关键字的使用 平时我们使用对象之间的传值都是采用retain count +1的方式,这种方式的适用于当对象的某属性的值改变时,引用该对象的不同指针会同时改变,因为这两个指针指向的是同一个内存地址, 但如果需求是,

CISCO-路由器交换机IOS被删,恢复方法

方式一,tftpdnld方式恢复Router 2600 IOS 1) 将计算机串口和路由器console口相连 一定将计算机网口与路由器第一个以太口f0/0相连. 2) 启动TFTP服务器,并将要下载的版本放于指定目录下面 3) 冷启动路由器,在开机的前60秒之内,按住“Ctrl+Break”键 4) 这时系统会进入灾难恢复模式,其提示符为“Rommon1>” 5) Rommon1>IP_ADDRESS=192.168.1.2 (设置f0/0口的IP地址为192.168.1.2) 6) Rom

ObjectiveC 深浅拷贝学习

1.IOS Copy什么时候用? 在O-C里面有个值对象的概念,当你新定义一个属性是值对象时就应该用copy来修饰.那么都什么对象是值对象呢? 值对象是指封装了基本值(属于 C 数据类型)且提供与该值相关的服务的对象.值对象以对象形式表示标量类型.Foundation 框架向您提供了以下类(这些类产生对象,用于字符串.二进制数据.日期与时间.数字以及其他值):NSString和NSMutableString NSData和NSMutableData NSDate NSNumber NSValue

记一次ASA固件被误删除后应急故障响应预案的修复思路与过程

又是一个周末,在不断提升自己的语言能力和技术能力的每天,我都会非常的苛刻要求自己保持学习的劲头,保持清醒.今天我相信我的目标清单能指引我努力完成很多我想做的事情.不管未来转型做集成,还是深入下去做网工,我都希望有那么一天能不曾后悔自己曾经努力而为之付出了一整个青春的东西--技术. 今天同样也带来一个非常基础但是又极其使用的场景应用的思路与操作方案.ASA固件被误操作丢失以及dir目录下所有文件丢失修复思路与方法. 写在前面: 我在遇到此场景的时候,确实在百度和Google上查过资料,但实际情况是

[转] cordova-plugin-x-toast

本文转自:https://www.npmjs.com/package/cordova-plugin-x-toast cordova plugin add https://github.com/EddyVerbruggen/Toast-PhoneGap-Plugin.git 0. Index Description Screenshots Installation Automatically (CLI / Plugman) Manually PhoneGap Build Usage Styling

IOS开发之copy的问题

copy的目的就是修改副本,修改原始对象和副本时不会产生干扰. 定义一个不可变属性A,再定义一个可变属性B.用B做添加删除等操作后再将B赋值给A时,有些人习惯用A = B:其实这样是不安全的. 假设有下面的一段代码: ? 1 2 3 4 5 6 7 8 9 10   int main() {    NSMutableString *strM = [NSMutableString [email protected]"123"];    NSString *str = strM;    N