iOS对象的拷贝
一 :拷贝的相关概念
copy语法的目的:改变副本的时候,不会影响到源对象;
深拷贝:内容拷贝,会产生新的对象。新对象计数器置为1,源对象计数器不变。
浅拷贝:指针拷贝,不会产生新的对象。源对象计数器+1。
二:拷贝的实现
实现copy,必须实现<NSCopying>协议 ,即 copyWithZone方法,返回一个不可变对象。
实现mutableCopy,必须实现<NSMutableCoping>协议,即 mutableCopyWithZone方法 ,返回一个可变对象。
对于数组,字典,字符串 等都已经实现了<NSCopying>的协议。
三:数组、字典、字符串等拷贝原则
1.对于系统的非容器类的拷贝
对于不可变对象 ,copy实际是浅拷贝,mutableCopy是深拷贝。
对于可变对象 ,copy、mutableCopy都是深拷贝
2.对于系统的容器类的拷贝
以上原则同样是适用的,但是容器类的对象都是指针拷贝。
如果想要元素对象也是对象复制,就需要实现深拷贝。
四:自定义对象的拷贝
Person.h
#import@interface Person : NSObject
@property (nonatomic,retain) NSMutableArray *apples;
@property (nonatomic,assign) int age;
@end
Person.m
#import "Person.h"
@implementation Person
- (id)copyWithZone:(NSZone *)zone{
Person *p = [[self class] allocWithZone:zone];
p.apples = [_apples mutableCopy];
p.age = _age;
return p;
}
@end
测试
Person *p = [[Person alloc] init];
p.apples = [NSMutableArray arrayWithObjects:@"iphone",@"ipad", nil nil];
p.age = 20;
Person *p1 = [p copy];
if(p != p1){
NSLog(@"p1.age=%d",p1.age);
NSLog(@"p1.apples=%@",p1.apples);
}
五:理解下property里的copy、strong区别
copy
#import@interface Person : NSObject
@property (nonatomic,copy ) NSString *name;
@end
NSMutableString *string = [[NSMutableString alloc] initWithString:@"1111"];
Person *person =[[Person alloc] init];
person.name = string;
[string appendString:@"1233"];
property copy 实际上就对name干了这个:
- (void)setName:(NSString *)name
{
_name = [name copy];
}
假设name为NSMutableString,会发生什么事?
@property (nonatomic, copy) NSMutableString *name;
实际上内部还是:
- (void)setName:(NSMutableString *)name
{
_name = [name copy];
}
copy出来的仍然是不可变字符!如果有人用NSMutableString的方法,就会崩溃:
[person.name appendString:@"1233"];
strong
@property (nonatomic, strong) NSString *name;
NSMutableString *string = [NSMutableString stringWithFormat:@"汉斯哈哈哈"];
HSPerson *person = [[HSPerson alloc] init];
person.name = string;
// 可以改变person.name的值,因为其内部没有生成新的对象
[string appendString:@" hans"];
NSLog(@"name = %@", person.name);