美文网首页
copy和mutableCopy实践

copy和mutableCopy实践

作者: YY_Lee | 来源:发表于2017-06-20 16:34 被阅读24次

    首先说下两个基本定义:
    浅复制:只copy指针而不是copy实际的资源,两个实例指向内存中统一资源。
    深复制:不仅复制指针还复制指针,还复制指针所指向的资源,副本对象的指针指向内存中不同位置的同一资源的副本。

    不可变对象的copy和mutableCopy操作:

    不可变数组
    NSArray *arr = [NSArray array];
    NSMutableArray  *arr1 = arr.copy;
    NSMutableArray *arr2 = arr.mutableCopy;
    NSLog(@"%p--%p--%p",arr,arr1,arr2);//0x60800001a1b0--0x60800001a1b0--0x608000047290 
    [arr2 insertObject:@"1" atIndex:0];//插入元素成功
    [arr1 insertObject:@"1" atIndex:0];//'-[__NSArray0 insertObject:atIndex:]: unrecognized selector sent to instance
    
     不可变字典
     NSDictionary *dict1 = [NSDictionary dictionaryWithObjectsAndKeys:@"value1",@"key1",@"value2",@"key2", nil];
     NSMutableDictionary *dicM = dict1.copy;
     NSMutableDictionary *dicM1 = dict1.mutableCopy;
     NSLog(@"%p--%p--%p",dict1,dicM,dicM1);//0x6000002641c0--0x6000002641c0--0x600000045280
     [dicM1 removeObjectForKey:@"key1"];
        Printing description of dicM1:
       {
          key2 = value2;
       }
    
     [dicM removeObjectForKey:@"key1"];//-[__NSDictionaryI removeObjectForKey:]: unrecognized selector sent to instance
    
     不可变字符串
     NSString *str = @"123";
     NSMutableString *strM1 = str.copy;
     NSMutableString *strM2 = str.mutableCopy;
     NSLog(@"%p--%p--%p",str,strM1,strM2);// 0x1047ee068--0x1047ee068--0x608000079800
     [strM2 appendString:@"4"];//Printing description of strM2:
    1234
     [strM1 appendString:@"5"]; //Attempt to mutate immutable object with appendString:   
    

    结论:对不可变对象进行copy操作,不会开辟新的内存,copy的只是内存地址;对不可变对象进行mutableCopy操作,会开辟新的内存,拷贝出的对象是可变的;

    可变对象的copy和mutableCopy操作:

    可变数组
    NSMutableArray *arrM = [NSMutableArray arrayWithCapacity:0];
    NSMutableArray *arrM1 = arrM.copy;
    NSMutableArray *arrM2 = arrM.mutableCopy;
    NSLog(@"%p--%p--%p",arrM,arrM1,arrM2);//arrM:0x608000047e60--arrM1:0x60800000f160--arrM2:0x608000047ce0
    [arrM insertObject:@"2" atIndex:0];
    [arrM2 insertObject:@"3" atIndex:0];
    [arrM1 addObject:@"1"];//-[__NSArray0 addObject:]: unrecognized selector sent to instance
    
    
    可变字典
    NSMutableDictionary *dict1 = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1",@"key1",@"value2",@"key2", nil];
    NSMutableDictionary *dicM = dict1.copy;
    NSMutableDictionary *dicM1 = dict1.mutableCopy;
    NSLog(@"%p--%p--%p",dict1,dicM,dicM1);//0x60000005d7f0--0x600000074780--0x60000005b810
    [dicM1 removeObjectForKey:@"key1"];
     Printing description of dicM1:
       {
          key2 = value2;
       }
    
    [dicM removeObjectForKey:@"key1"];//-[__NSDictionaryI removeObjectForKey:]: unrecognized selector sent to instance
    
    可变字符串
    NSMutableString *str = [NSMutableString stringWithCapacity:0]; 
    NSMutableString *strM1 = str.copy;
    NSMutableString *strM2 = str.mutableCopy;
    NSLog(@"%p--%p--%p",str,strM1,strM2);//0x6080000716c0--0x103d94570--0x608000071680
    [strM2 appendString:@"4"];//Printing description of strM2:
    4
    [strM1 appendString:@"5"];//Attempt to mutate immutable object with appendString:
    

    结论:对可变对象进行copy操作,会开辟新的内存,拷贝出的对象是不可变的;对可变对象进行mutableCopy操作,会开辟新的内存,拷贝出的对象是可变的;

    关于有可变类型的不可变类(如NSDictionary,NSArray,NSString),声明属性时内存管理关键字为什么要用copy?

    用strong声明结果如下:

    strong.png arrStrong.png strStrong.png

    用copy声明结果如下:

    copy.png arrCopy.png strCopy.png

    属性为可变类型,用strong定义,当属性赋值时接收的对象为可变对象,而该可变对象的值改变时,属性的值也跟着改变了。而用copy修饰,赋值时会拷贝出一个新的不可变对象,不受该可变对象影响;

    从上面的结果能看出copy不等于浅复制,而mutableCopy一定是深复制。这是因为拷贝后只要副本和原对象之间相互不影响即可,对于OC中这些不可变的对象,因为他们的值是不能修改的,所以副本和原对象之间满足相互不影响,没必要新开辟内存空间拷贝一份资源。

    相关文章

      网友评论

          本文标题:copy和mutableCopy实践

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