分享链接 http://www.jianshu.com/p/4e327d1832ef
分享链接2 iOS 深拷贝 和 浅拷贝
Copy 与 Strong 关键字的区别
1. copy 关键字 一般用来修饰 NSString , NSArray, NSDictionary 这些不可变 immutable CF(Core foundation) 对象
要理解多态 ,父类指针可以指向子类对象, 还有 NSRuntime 的这个 C 库的实现机制;
因为父类指针可以指向子类对象,使用 copy 的目的是为了让本对象的属性不受外界影响,使用 copy 无论给我传入是一个可变对象还是不可对象,
我本身持有的就是一个不可变的副本.这个时候我有一个不可变的副本在堆里面了;
2.如果我们使用是 strong ,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性.
copy 此特质所表达的所属关系与 strong 类似。然而设置方法并不保留新值,而是将其“拷贝” (copy)。 当属性类型为 NSString 时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个 NSMutableString 类的实例。这个类是 NSString 的子类,表示一种可修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变” (immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的” (mutable),就应该在设置新属性值时拷贝一份。
NSArray 我们知道他是一个不可变的容器; 我们使用它的初衷也是希望数据的指针绑定在不可变的容器;
但是如果仍然使用的是 Strong 指针, 有可能存在的情况是 , 在你不知情的情况, 数组里面的元素确实变了; 这往往是我们不想要的;
@property (nonatomic ,readwrite, strong) NSArray *array;
然后进行下面的操作:
NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithObjects:@11,@12, nil];
self.array = mutableArray;
[mutableArray removeAllObjects];
NSLog(@"first:%@",self.array);
NSArray *array = @[ @1, @2, @3, @4 ];
[mutableArray addObjectsFromArray:array];
self.array = [mutableArray copy];
NSLog(@"second:%@",self.array);
[mutableArray removeAllObjects];
NSLog(@"third:%@",self.array);
打印结果如下所示:copy 修饰结果
first:(
11,
12
)
2016-02-28 13:20:31.524 TestJellyPath[17203:899296] second:(
1,
2,
3,
4
)
2016-02-28 13:20:31.524 TestJellyPath[17203:899296] third:(
1,
2,
3,
4
)
strong 修饰 打印如下:
可以 看到 strong 修饰 部分 指针指向内容确实是可变 的 , 而经过 [first:(
)
2016-02-28 13:20:31.524 TestJellyPath[17203:899296] second:(
1,
2,
3,
4
)
2016-02-28 13:20:31.524 TestJellyPath[17203:899296] third:(
1,
2,
3,
4
)
mutableArray
copy] 方法的调用(递归调用 copyWithZone)之后 , 又重新 copy 了一份不可变的内容 到堆里
为了理解这种做法,首先要知道,两种情况:
对非集合类对象的 copy 与 mutableCopy 操作;
对集合类对象的 copy 与 mutableCopy 操作。
- 对非集合类对象的copy操作:
在非集合类对象中:对 immutable 对象进行 copy 操作,是指针复制,mutableCopy 操作时内容复制;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。用代码简单表示如下:
[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //深复制
[mutableObject copy] //深复制
[mutableObject mutableCopy] //深复制
比如以下代码:
NSMutableString *string = [NSMutableString stringWithString:@"origin"];//copy
NSString *stringCopy = [string copy];
查看内存,会发现 string、stringCopy 内存地址都不一样,说明此时都是做内容拷贝、深拷贝。即使你进行如下操作:
[string appendString:@"origion!"]
stringCopy 的值也不会因此改变,但是如果不使用 copy,stringCopy 的值就会被改变。 集合类对象以此类推。 所以,
用 @property 声明 NSString、NSArray、NSDictionary 经常使用 copy 关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,他们之间可能进行赋值操作,为确保对象中的字符串值不会无意间变动,应该在设置新属性值时拷贝一份。
2、集合类对象的copy与mutableCopy
集合类对象是指 NSArray、NSDictionary、NSSet ... 之类的对象。下面先看集合类immutable对象使用 copy 和 mutableCopy 的一个例子:
NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"]];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
查看内容,可以看到 copyArray 和 array 的地址是一样的,而 mCopyArray 和 array 的地址是不同的。说明 copy 操作进行了指针拷贝,mutableCopy 进行了内容拷贝。但需要强调的是:此处的内容拷贝,仅仅是拷贝 array 这个对象,array 集合内部的元素仍然是指针拷贝。这和上面的非集合 immutable 对象的拷贝还是挺相似的,那么mutable对象的拷贝会不会类似呢?我们继续往下,看 mutable 对象拷贝的例子:
NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
查看内存,如我们所料,copyArray、mCopyArray和 array 的内存地址都不一样,说明 copyArray、mCopyArray 都对 array 进行了内容拷贝。同样,我们可以得出结论:
在集合类对象中,对 immutable 对象进行 copy,是指针复制, mutableCopy 是内容复制;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。但是:集合对象的内容复制仅限于对象本身,对象元素仍然是指针复制。用代码简单表示如下:
[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //单层深复制
[mutableObject copy] //单层深复制
[mutableObject mutableCopy] //单层深复制其实对 集合对象的深拷贝 , 也可以理解为 对这个指针指向部分的右值的 copy ; 这个c语言里面的内容;