OC深浅拷贝


在OC中,对象、block存在深浅拷贝,其拷贝的在不同的情况下也不相同,以下就是针对对不同情况下深浅拷贝的详解:

retain :始终是浅拷贝,引用计数每次加1,返回对象是否可变跟对象是否可变完全一致。

copy :对于可变对象为深拷贝,引用计数不变,对于不可变对象是浅拷贝,引用计数每次加1.始终返回一个不可变对象。

mutableCopy:对于任何对象都是深拷贝,引用计数不变,始终返回一个可变对象。

总结:对于系统类的对象,除了NSString、NSNumber、NSArray、NSDictionary的copy是浅拷贝,其他情况都是深拷贝。而且不管被拷贝的对象是否为可变的,copy后的对象都是不可变的,mutableCopy之后的对象都是可变的。对于我们手动创建的对象,其是可变对象,所有其copy也是深拷贝,mutableCopy也是深拷贝,这两种拷贝返回的对象都是可变的。

下面是针对不同情况的详细说明:

(1)系统容器类对象(NSArray、NSDictionary)

1.NSArray and NSMutableArray

   

                        NSArray

    **************************************************

 

            NSArray *arr1 = [[NSArray alloc]initWithObjects:@"zhangsan",@"lisi",@"wangwu" , nil];

            NSArray *arr2 = [arr1 copy];

            NSMutableArray *arr3 = [arr1 mutableCopy];

                NSLog(@"<%p>,<%p>,<%p>",arr1,arr2,arr3);

                for (NSString *str  in arr1) {

                    NSLog(@"str1=%p:%@",str,str);

                }

                for (NSString *str  in arr2) {

                    NSLog(@"str2=%p:%@",str,str);

                }

                for (NSString *str  in arr3) {

                    NSLog(@"str3=%p:%@",str,str);

                }

 

 //从结果来说,可以看出,NSArray copy是浅拷贝,mutableCopy是深拷贝,而数组里面的内容都是浅拷贝

 

                         NSMutableArray

************************************************************************

        NSMutableArray *arr1 = [[NSMutableArray alloc]initWithObjects:@"zhangsan",@"lisi",@"wangwu" , nil];

        NSMutableArray *arr2 = [arr1 copy];

        NSMutableArray *arr3 = [arr1 mutableCopy];

        NSLog(@"<%p>,<%p>,<%p>",arr1,arr2,arr3);

        for (NSString *str  in arr1) {

            NSLog(@"str1=%p:%@",str,str);

        }

        for (NSString *str  in arr2) {

            NSLog(@"str2=%p:%@",str,str);

        }

        for (NSString *str  in arr3) {

            NSLog(@"str3=%p:%@",str,str);

        }

        //从结果来说,NSMutableArray 的copy、mutableCopy都是深拷贝。而数组里面的内容是浅拷贝。           

 

小结:除了NSArray 的copy是浅拷贝,其他情况都是深拷贝,而且Array内的元素都是浅拷贝。

2.NSDictionary and NDMutableDictionary

                     

     <span style="white-space:pre">			</span> NSDictionary 
*************************************************************

        NSDictionary *dic1 = [[NSDictionary alloc]initWithObjectsAndKeys:@"zhangsan",@"张三",@"lisi",@"李四",@"wangwu",@"王五",nil];

 

         NSDictionary *dic2 = [dic1 copy];

          NSMutableDictionary *dic3 = [dic1 mutableCopy];

            NSLog(@"<%p>,<%p>,<%p>",dic1,dic2,dic3);

            for (NSString *str  in dic1) {

                NSLog(@"str1=%p:%@",str,str);

            }//打印dic1

            for (NSString *str  in dic2) {

                NSLog(@"str2=%p:%@",str,str);

            }//打印dic2

            for (NSString *str  in dic3) {

                NSLog(@"str3=%p:%@",str,str);

            }//打印dic3

从结果可以看出,NSDictionary 的copy是浅拷贝,mutableCopy是深拷贝,其中的数组元素也是浅拷贝

 

*********************************************************************

                    NSMutableDictionary

            NSMutableDictionary *dic4 = [[NSMutableDictionary alloc]initWithObjectsAndKeys:@"zhangsan",@"张三",@"lisi",@"李四",@"wangwu",@"王五",nil];

 

            [dic4 setObject:@"wangmazi" forKey:@"王麻子"];

            NSMutableDictionary *dic5 = [dic4 copy];

            NSMutableDictionary *dic6 = [dic4 mutableCopy];

 

            NSLog(@"<%p>,<%p>,<%p>",dic4,dic5,dic6);

 

            for (NSString *str  in dic4) {

                NSLog(@"str4=%p:%@",str,str);

            }//打印dic4

            for (NSString *str  in dic5) {

                NSLog(@"str5=%p:%@",str,str);

            }//打印dic5

            for (NSString *str  in dic6) {

                NSLog(@"str6=%p:%@",str,str);

            }//打印dic6

 

从结果来看,NSMutableDictionary的copy、mutableCopy拷贝都是深拷贝,其内容也都是浅拷贝。

 

小结: 除了NSDictionary的copy是浅拷贝,其他都是深拷贝,字典内部的元素也是浅拷贝。


(2)系统非容器类对象 (NSString、NSNumber)

1.NSString and NSMutablString

    

                              NSString

****************************************************************

       NSString *str = [[NSString alloc] initWithFormat:@"hello_%d",1];

        //1.NSString 使用copy后的对象是不可变的。相当于浅拷贝

        NSString *seceondStr = [str copy];

        NSLog(@"secondStr:%@",seceondStr);

 

        //2.NSString 使用MutableCopy 之后 的对象是可变的,相当于深拷贝

        NSMutableString *thirdStr = [str mutableCopy];

        [thirdStr appendString:@"333"];

        NSLog(@"thirdStr:%@",thirdStr);

 

  <pre name="code" class="objc">**************************<span style="font-family: Arial, Helvetica, sans-serif;"> NSMutableString****************************************************************</span>
NSMutableString *str = [[NSMutableString alloc]initWithString:@"hello"]; //3.NSMutableString 使用copy之后的对象是不可改变的,相当于深拷贝, NSMutableString *secondStr = [str copy]; //[secondStr appendString:@"222"];不可增加,即不可变 NSLog(@"secondStr:%@",secondStr); //4,NSMutableString 使用 MutableCopy之后的对象是可改变的。相当于深拷贝 NSMutableString *thirdStr = [str mutableCopy]; [thirdStr appendString:@"3333"]; NSLog(@"thirdStr : %@",thirdStr); 小结:除了NSString的copy是浅拷贝,其他都是深拷贝
 

2.NSNumber的结果与NSString类似,在此省略

(3)手动创建的类对象

对于我们手动创建的类,我们如果要想实现copy,必须显示的采用OC提供的NSCoping、NSMutableCoping协议,实现这两个协议的方法copyWithZone:(NSZone )zone 和mutableCopyWithZone:(NSZone )zone.

例子:

        //声明一个Person类,继承与NSObject类,并显示的采用NSCopying,NSMutableCopying协议

        @interface Person : NSObject <NSCopying,NSMutableCopying>

        @property (nonatomic,copy)NSString *name;//姓名

        @property (copy,nonatomic)NSString *address;//地址

        @end

 

        //类的实现,

        @implementation Person

        - (NSString *)description

        {

            return [NSString stringWithFormat:@"person's info is :name = %@,address= %@", self.name,self.address];

        }

        //实现协议NSCopying的方法copyWithZone:(NSZone *)zone

        - (id)copyWithZone:(NSZone *)zone{

            Person *temp = [[[self class] allocWithZone:zone]init];

            temp.name = _name;

            temp.address = _address;

            return temp;

        }

        //实现协议NSMutableCopying的方法mutableCopyWithZone:(NSZone *)zone

        - (id) mutableCopyWithZone:(NSZone *)zone{

            Person *mTemp = [[Person allocWithZone:zone]init];

            mTemp.name = [_name copy];

            mTemp.address = [_address copy];

            return  mTemp;

        }

        @end

 

        在main方法中:

        //创建一个类对象,并初始化其信息

         Person *person = [[Person alloc]init];

        person.name = @"zhangsan";

        person.address  = @"henan";

        NSLog(@"count:%lu",person.retainCount);

        NSLog(@"<%p>:<%p>:<%p>%@",person,person.name,person.address,person);

 

        //实现copy对象,并打印其信息

        Person *cPerson = [person copy];

        cPerson.name = @"lisi";

        cPerson.address =@"hebei";

        NSLog(@"count:%lu",person.retainCount);

        NSLog(@"<%p>:<%p>:<%p>%@",cPerson,cPerson.name,cPerson.address,cPerson);

 

        //实现mutableCopy对象,并打印其信息

        Person *mcPerson = [person mutableCopy];

        mcPerson.name = @"wnagwu";

        mcPerson.address = @"beijing";

 

        NSLog(@"count:%lu",person.retainCount);

        NSLog(@"<%p>:<%p>:<%p>%@",mcPerson,mcPerson.name,mcPerson.address,mcPerson);

 

        结果为:

        -------------------before copy and mutableCopy------------------

         person'retainCount:1

        <0x1001065a0>:<0x100002350>:<0x100002370>person's info is :name = zhangsan,address= henan

        -------------------after copy------------------

        person'retainCount:1

        <0x100500110>:<0x1000023d0>:<0x1000023f0>person's info is :name = lisi,address= hebei

        -------------------after mutableCopy------------------

        person'retainCount:1

        <0x100107060>:<0x100002410>:<0x100002430>person's info is :name = wnagwu,address= beijing

 

从结果可以看出:person对象是一个可变对象,其调用copy、mutableCopy方法之后返回的对象都是可变的,而且都是深拷贝。

本文参考了kissing_huo的 oc中的深浅拷贝

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值