Objective-C中深拷贝与浅拷贝简述

ios开发过程中,大体上会区分为两个概念:

  1. 对象(如NSString,NSNumber等类型)
  2. 容器(如NSArray,NSDictionary等类型)
  • 对象
    • copy后拿到的对象也是和copy的对象指向同一内存地址,copy的对象引用指数+1,拷贝的只是对象的一个指针是浅拷贝
    • mutablecopy后拿到的对象与mutablecopy的对象所处于内存不同的位置,内存的内容一样,拷贝对象引用计数不会+1,新拷贝出来的对象引用计数为1,拷贝的不单是内存内容,还新分配一块内存,是深拷贝
  • 容器
    • 也参照如上方法copy出来的对象是浅拷贝,mutablecopy出来的对象是深拷贝,但是需要记住,容器的包含对象(元素)的拷贝,对他们的容器无论使用copy得到的容器对象引用,还是mutablecopy得到的新容器对象,他们里面所包含的元素对象都将是浅拷贝。所有对新旧对象里面的元素修改都会影响上下文。
    • 要想实现对象的深拷贝,必须自己提供拷贝的方法。
    • 官方文档中介绍两种实现深拷贝的方法:
      • a.用Array的initWithArray: copyItems函数,如下:
        • NSArray *deepCopyArray=[[NSArray alloc] initWithArray: someArray copyItems: YES];
        • 调用后,会对原NSArray中的每个元素调用其copy函数,并把返回的id加入到新的数组中。所以这是依赖于Obj对象类实现的深拷贝,如果- (id)copywithZone:(NSZone*)zone是重新分配一块内存赋值后返回,那么就是真正的深拷贝。如果直接返回自身,那么它只是浅拷贝。
      • b.用archiver方式:
        • NSArray* trueDeepCopyArray = [NSKeyedUnarchiverunarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject:oldArray]];
        • 这是真正意义上的深拷贝,不依赖于实际类Copying协议的实现。
  • 对于拥有可变版本的类型如NSString,NSArray等使用copy与mutablecopy还需注意:
    1. copy得到的对象是不可变类型
    2. mutablecopy得到的对象是可变类型
      • 一不注意便会让一个可变类型的变量去持有copy出来的对象,然后调用变量的add或remove等方法程序便崩掉。

 

posted @ 2016-03-13 02:28  Jk_Chan  阅读(702)  评论(0编辑  收藏  举报