目录
1. 前言
2. 概念
在开发的时候,使用copy的频率还是挺高的,我们只要copy定义的属性的设置方法并不保留新值,只是其拷贝一份值,为什么NSString、NSArray、NSDictionary属性的定义说那个copy,如果使用strong关键字有什么问题?所以这节就讲一下以及什么使用深拷贝和浅拷贝的问题。

系统非集合类对象指的是 NSString, NSNumber ... 之类的对象。下面先看个非集合类immutable对象拷贝的例子
NSString *string = @"origin";
NSString *stringCopy = [string copy];
NSMutableString *stringMCopy = [string mutableCopy];通过查看内存,可以看到 stringCopy 和 string 的地址是一样,进行了指针拷贝;而 stringMCopy 的地址和 string 不一样,进行了内容拷贝;
再看mutable对象拷贝例子:
NSMutableString *string = [NSMutableString stringWithString: @"origin"];
//copy
NSString *stringCopy = [string copy];
NSMutableString *mStringCopy = [string copy];
NSMutableString *stringMCopy = [string mutableCopy];
//change value
[mStringCopy appendString:@"mm"]; //crash
[string appendString:@" origion!"];
[stringMCopy appendString:@"!!"];运行以上代码,会在第7行crash,原因就是 copy 返回的对象是 immutable 对象。注释第7行后再运行,查看内存,发现 string、stringCopy、mStringCopy、stringMCopy 四个对象的内存地址都不一样,说明此时都是做内容拷贝。
在非集合类对象中得出结论:
5.1 对不可变集合类:
不可变集合类对象是指NSArray、NSDictionary、NSSet ... 之类的对象。下面先看集合类immutable对象使用copy和mutableCopy的一个例子:
NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
[mCopyArray addobject: @"e"];查看内容,可以看到copyArray和array的地址是一样的,而mCopyArray和array的地址是不同的。说明copy操作进行了指针拷贝,mutableCopy进行了内容拷贝。mCopyArray可以添加对象,是可变对象。
强调:此处的内容拷贝,仅仅是拷贝array这个对象,array集合内部的元素仍然是指针拷贝。
5.2 对可变集合类:
可变集合类对象是指NSMutableArray、NSMutableDictionary、NSMutableSet ... 之类的对象。下面先看集合类immutable对象使用copy和mutableCopy的一个例子
NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
NSArray *copyArray = [array copy];
NSMutableArray *m1CopyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
[mCopyArray addObject:@"d"];
[m1CopyArray addObject:@"d"]; //crash查看内存,
(lldb) po array
<__NSArrayM 0x600001963540>(
a,
b,
c
)(lldb) po copyArray
<__NSArrayI 0x6000019635d0>(
a,
b,
c
)(lldb) po mCopyArray
<__NSArrayM 0x600001963390>(
a,
b,
c,
d
)(lldb) po m1CopyArray
<__NSArrayI 0x600001963570>(
a,
b,
c
)打印的地址可以得出结论:
在集合类对象中,对immutable对象进行copy,是指针复制,mutableCopy是内容复制。在集合类对象中,对mutable对象进行copy和mutableCopy都是内容复制。在集合类对象中,对对象进行copy的对象就是不可变的,进行mutable就是可变的copy 此特质所表达的所属关系与 strong 类似。然而设置方法并不保留新值,而是将其“拷贝” (copy)。当属性类型为 NSString 时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个 NSMutableString 类的实例。这个类是 NSString 的子类,表示一种可修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变” (immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的” (mutable),就应该在设置新属性值时拷贝一份。例如:
//定义一个以 strong 修饰的 array:
@property (nonatomic ,readwrite, strong) NSArray *array;进行如下操作
NSArray *array = @[ @1, @2, @3, @4 ];
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array];
self.array = mutableArray;
[mutableArray removeAllObjects];;
NSLog(@"self.array:%@",self.array);
[mutableArray addObjectsFromArray:array];
self.array = [mutableArray copy];
[mutableArray removeAllObjects];;
NSLog(@"self.array:%@",self.array);打印结果如下所示:
self.array:(
),
self.array:(
1,
2,
3,
4
)结果说明如果使用strong来定义不可变对象,它的子类可变对象,有可能该对象的指针指向他的子类,他的子类改变了,该对象也就改变了。这样就不经意篡改了该对象的值,不安全了。
通过本文,可以大概总结一下几点: