无论使用什么语言编程我们都必须考虑深拷贝和浅拷贝的问题,只是Objective-c提供了一个实现深拷贝的标准机制而已。所谓浅拷贝其实就是指针的赋值,例如:
NSString* str1 = @"Hello World!"; NSString* str2 = str1; 此时str1和str2同时指向了内存中的同一片区域,无论使用哪个指针对该区域进行了改动,使用另一个指针获取到的内容也会随之变化。这就是所谓的浅拷贝。而所谓的深拷贝是重新申请一块区域,重新建立一个对象,同时将原有对象的内容全部复制过来。例如:
NSString* str1 = @"Hello World!" NSString* str2 = [str1 copy]; 此时,无论操作哪个指针对其内容进行修改,另外一个指针所指示的内容不会受到影响。这里多说一句,调用NSString的copy函数复制出来的对象实际和原有对象指向的是同一片区域。但是如果如果对其指向的内容进行修改的话,因为NSString属于不可改变(immutable)对象,所以系统会重新申请一片空间,写入修改后的内容返回给该指针。而另外一个指向原来区域的指针不受任何影响。如下:
int main(int argc, const char * argv[]) { @autoreleasepool { NSString* str = @"hello world"; NSString* str1 = [str copy]; NSLog(@"str:%p, str1:%p", str, str1); str = @"liyazhou"; NSLog(@"str:%@, str1:%@", str, str1); NSLog(@"str:%p, str1:%p", str, str1); } return 0; } 得到的结果是:
对于常用的类型,这两个协议都已经实现,所以用户只需要调用copy和mutableCopy方法即可,但是对于自定义的类,要想使用copy方法就必须自己实现该协议。例如:
#import <Foundation/Foundation.h> @interface Person : NSObject<NSCopying> { } @property (nonatomic, strong) NSString* name; @property (nonatomic) int age; -(instancetype)init; -(id)copyWithZone:(NSZone *)zone; @end #import "Person.h" @implementation Person -(instancetype)init { self = [super init]; if(self) { _name = @"李牙刷儿"; _age = 25; } return self; } -(id)copyWithZone:(NSZone *)zone { Person *p = [[Person allocWithZone:zone]init]; p.name = self.name; p.age = self.age; return p; } @end