美文网首页
iOS浅拷贝和深拷贝

iOS浅拷贝和深拷贝

作者: Jey | 来源:发表于2018-11-30 17:10 被阅读14次

    浅拷贝:拷贝指向原来对象的指针,使原对象的引用计数+1,可以理解为创建了一个指向原对象的新指针而已,并没有创建一个全新的对象。


    浅拷贝.png
    NSString *str1 = @"str1";
    NSString *str2 = [str1 copy];
    NSLog(@"\nstr1 = %@ str1P = %p \n str2 = %@ str2P = %p", str1, str1, str2, str2);
    
    /*输出结果
    str1 = str1 str1P = 0x104d75180
    str2 = str1 str2P = 0x104d75180
    */
    

    深拷贝:拷贝出和原来仅仅是值一样,但是内存地址完全不一样的新的对象,创建后和原对象没有任何关系。


    深拷贝.png
    NSMutableString *mStr1 = [NSMutableString stringWithString:@"123"];
    NSMutableString *mStr2 = [mStr1 mutableCopy];
    NSLog(@"\n mStr1 = %@ mStr1P = %p \n mStr2 = %@ mStr2P = %p", mStr1, mStr1, mStr2, mStr2);
    /*输出结果
           mStr1 = 123 mStr1P = 0x6000004460c0
           mStr2 = 123 mStr2P = 0x600000446420
    */
    开辟了新的内存空间
    
    可变对象NSMutableString
    - (void) mutableNSStringTest
    {
        NSMutableString *mstr1 = [NSMutableString stringWithString:@"test002"];
        
        NSMutableString *mstr2 = [mstr1 copy];
        
        //[str2 appendString:@"test"]; //copy返回的是不可变对象,mstr2不能被修改,因此会发生崩溃
        
        NSMutableString *mstr3 = [mstr1 mutableCopy];
        [mstr3 appendString:@"modify"];
        
        NSLog(@"mstr1:%p - %@ \r\n",mstr1,mstr1);
        NSLog(@"mstr2:%p - %@ \r\n",mstr2,mstr2);
        NSLog(@"mstr3:%p - %@ \r\n",mstr3,mstr3);
    }
    
    2017-07-20 18:14:35.789 beck.wang[1433:180881] mstr1:0x610000075e40 - test002 
    2017-07-20 18:14:35.790 beck.wang[1433:180881] mstr2:0xa323030747365747 - test002 
    2017-07-20 18:14:35.790 beck.wang[1433:180881] mstr3:0x610000074480 - test002modify
    

    分析:mstr1、mstr2、mstr3 地址都不同,NSMutableString对象copy与mutableCopy都是深拷贝,且copy返回的对象是不可变对象。
    总结一波:copy不可变对象时是浅拷贝,copy可变对象时是深拷贝,mutableCopy是深拷贝

    再来看一段代码
        NSString *str1 = @"str1";
        NSString *str2 = [str1 copy];
        
        str1 = @"asdf";
    
        NSLog(@"\nstr1 = %@ str1P = %p \n str2 = %@ str2P = %p", str1, str1, str2, str2);
    
        /*输出结果,修改str2 同理
           str1 = asdf str1P = 0x10776b1a0
           str2 = str1 str2P = 0x10776b180
         */
    

    这里不是说copy是浅拷贝吗?str1 和 str2 指向同一个内存空间,str1变化,str2的值也会变化。

    但是copy还有它的特点:

    修改源对象的属性和行为,不会影响副本对象
    修改副本对象的属性和行为,不会影响源对象

    自定义类实现copy的步骤:

    (1)遵守NSCoping协议
    (2)实现copyWithZone方法。//参数zone基本不用,它的意思是指定该方法从始至终都在某一个区域分配内存
    (所有copy最终都会调用这个方法)
    {
      //方法内部进行以下操作
      //(1)实例化对象
      A* a = [A alloc ]init]; //一般正规写法是[[self.class alloc] init] 因为这样子类也可以复用该方法
      //(2)给属性赋值
      a.xx = xx;
      //(3)返回新对象
      return a;
    }

    #import <Foundation/Foundation.h>
    
    /*
     创建一个Teacher类,并让该类实现copy方法
     */
    
    //1.遵守NSCopying协议
    @interface Teacher : NSObject<NSCopying>
    @property(nonatomic,copy)NSString* name;
    //2.实现copyWithZone方法;
    -(id)copyWithZone:(NSZone *)zone;
    @end
    
    #import "Teacher.h"
    
    @implementation Teacher
    //实现copyWithZone方法
    -(id)copyWithZone:(NSZone *)zone
    {
        Teacher* teacher = [[self.class alloc]init];
        teacher.name = self.name;
        return teacher;
    }
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        Teacher* teacher = [[Teacher alloc]init];
        teacher.name = @"我是园丁";
        
        Teacher* teacher1 = [teacher copy];
       
        NSLog(@"teacher:%p-%@",teacher,teacher.name);
        NSLog(@"teacher1:%p-%@",teacher1,teacher1.name);
    }
    
    运行结果:
    2015-08-15 16:41:07.821 copy的那些事[1779:148657] teacher:0x7fd750d13ce0-我是园丁
    2015-08-15 16:41:07.822 copy的那些事[1779:148657] teacher1:0x7fd750d13cf0-我是园丁
    

    上面代码如果没有实现NSCopying协议,-[Person copyWithZone:]: unrecognized selector sent to instance 0x60000022b6a0

    相关文章

      网友评论

          本文标题:iOS浅拷贝和深拷贝

          本文链接:https://www.haomeiwen.com/subject/bavhcqtx.html