• 深浅拷贝


    首先关于copy和mutableCopy的行为:不管是NSString这种元素类、还是NSArray这样的容器类、还是Mutable和非Mutable类,copy和mutableCopy调用后表现的行为到底是什么样完成取决于类本身NSCopying和NSMutableCopying协议是如何实现的。

    想要正常调用copy和mutableCopy两个函数,那么类就一定要实现对应的协议。

    1.      元素数据的copy和mutableCopy。

    常用的NSString类,示例代码如下:

    1. NSString* string = @”a”;  
    2. NSString* stringCopy = [string copy];// stringCopy与string地址相同,retainCount+ 1  
    3. NSMutableString* stringMCopy = [string mutablecopy];// stringMCopy与string地址不同  
    4.    
    5. NSMutableString* stringM1 = [stringMCopy copy];//地址与stringMCopy不同,且为不可修改  
    6. NSMutableString* stringM2 = [stringMCopy mutablecopy];//地址与stringMCopy不同,可修改   

    可以基本推出NSString和NSMutableString中两个协议的实现

    1. NSString:  
    2. - (id)copywithZone:(NSZone*)zone  
    3. {  
    4.   return self;  
    5. }  
    6.    
    7. - (id)mutableCopywithZone:(NSZone*)zone  
    8. {  
    9.   NSMutableString* copy =[[NSMutableString alloc] initxxxxxx];  
    10.   ....  
    11.   return copy;  
    12. }  
    13. NSMutableString:  
    14. - (id)copywithZone:(NSZone*)zone  
    15. {  
    16.   NSString* copy = [[NSStringalloc] initxxxxxx];  
    17.   ....  
    18.   return copy;//所以不可修改  
    19. }  
    20.    
    21. - (id)mutableCopywithZone:(NSZone*)zone  
    22. {  
    23.   NSMutableString* copy =[[NSMutableString alloc] initxxxxxx];  
    24.   ....  
    25.   return copy;  
    26. }  

    2.      容器类的copy和mutableCopy。

    常用类NSArray和NSMutableArray,看如下示例代码:

    1. Class1* obj1= ....;//正常初始化  
    2. NSArray* array = [[NSArray alloc] initWithObjects:obj1, nil];  
    3. NSArray* arrayCopy = [array copy];//地址不变,retaincount+1  
    4. NSMutableArray* arrayMCopy = [array mutableCopy];//地址改变,但是数组中成员指针和obj1相同,浅拷贝  
    5.   
    6. NSMutableArray* arrayM1 = [arrayMCopy Copy];//地址改变,但是数组中成员指针和obj1相同,浅拷贝。arrayM1为NSArray不可修改  
    7. NSMutableArray* arrayM2 = [arrayMCopy mutableCopy];//地址改变,但是数组中成员指针和obj1相同,浅拷贝  
    1. //推断  
    1. NSArray:  
    2. - (id)copywithZone:(NSZone*)zone  
    3. {  
    4.   //伪码  
    5.   return [self retain];  
    6. }  
    7.   
    8. - (id)mutableCopywithZone:(NSZone*)zone  
    9. {  
    10.   NSMutableArray* copy = [[NSMutableString alloc] initxxxxxx];  
    11.   for (id element in self) {  
    12.     [copy addObject:element];//element retian count + 1  
    13.     ....  
    14.   }  
    15.   return copy;  
    16. }  
    17.   
    18. NSMutableArray:  
    19. - (id)copywithZone:(NSZone*)zone  
    20. {  
    21.   NSArray* copy = [[NSArray alloc] initXXX];  
    22.   /*把每个element加入到copy数组,retainCount+1*/  
    23.   ....  
    24.   return copy;  
    25. }  
    26.   
    27. - (id)mutableCopywithZone:(NSZone*)zone  
    28. {  
    29.   NSMutableArray* copy = [[NSMutableString alloc] initxxxxxx];  
    30.   for (id element in self) {  
    31.     [copy addObject:element];//element retian count + 1  
    32.     ....  
    33.   }  
    34.   return copy;  
    35. }  

    3.      深拷贝

    上面提到的官方文档中介绍两种实现深拷贝的方法:

    a.      用Array的initWithArray:  copyItems函数,如下:

    NSArray *deepCopyArray=[[NSArray alloc] initWithArray: someArraycopyItems: YES];

    调用后,会对原NSArray中的每个元素调用其copy函数,并把返回的id加入到新的数组中。所以这是依赖于Obj对象类实现的深拷贝,如果- (id)copywithZone:(NSZone*)zone是重新分配一块内存赋值后返回,那么就是真正的深拷贝。如果直接返回自身,那么它只是浅拷贝。

    b.      用archiver方式:

    NSArray* trueDeepCopyArray = [NSKeyedUnarchiverunarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject:oldArray]];

    这是真正意义上的深拷贝,不依赖于实际类Copying协议的实现。

    4. 用Category实现自定义的深拷贝deepmutableCopy,如:

      1. - (NSMutableArray *)mutableDeepCopy  
      2. {  
      3.     NSMutableArray *ret = [[NSMutableArrayalloc] initWithCapacity:[self count]];  
      4.     for (id value in self)  
      5.     {  
      6.         id oneCopy = nil;  
      7.         if ([value respondsToSelector:@selector(mutableDeepCopy)])  
      8.             oneCopy = [value mutableDeepCopy];  
      9.         else if ([value respondsToSelector:@selector(mutableCopy)])  
      10.             oneCopy = [value mutableCopy];  
      11.         if (oneCopy == nil)  
      12.             oneCopy = [value copy];  
      13.         [ret addObject: oneCopy];  
      14.     }  
      15.     return ret;  
      16. }  
  • 相关阅读:
    [leetcode] N-Queens
    [leetcode] Minimum Path Sum
    [leetcode] Longest Valid Parentheses
    习题9-1 时间换算
    long常量和long long常量
    整数占用空间
    来到地球多久啦
    习题8-10 输出学生成绩
    习题8-7 字符串排序
    习题8-9 分类统计各类字符个数
  • 原文地址:https://www.cnblogs.com/W-Kr/p/5194328.html
Copyright © 2020-2023  润新知