zoukankan      html  css  js  c++  java
  • iOS-深浅拷贝

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

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

    1.  元素数据的copy和mutableCopy。

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

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

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

    NSString:
    - (id)copywithZone:(NSZone*)zone
    {
      return self;
    }
     
    - (id)mutableCopywithZone:(NSZone*)zone
    {
      NSMutableString* copy =[[NSMutableString alloc] initxxxxxx];
      ....
      return copy;
    }
    NSMutableString:
    - (id)copywithZone:(NSZone*)zone
    {
      NSString* copy = [[NSStringalloc] initxxxxxx];
      ....
      return copy;//所以不可修改
    }
     
    - (id)mutableCopywithZone:(NSZone*)zone
    {
      NSMutableString* copy =[[NSMutableString alloc] initxxxxxx];
      ....
      return copy;
    }

    2.   容器类的copy和mutableCopy。

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

    Class1* obj1= ....;//正常初始化
    NSArray* array = [[NSArray alloc] initWithObjects:obj1, nil];
    NSArray* arrayCopy = [array copy];//地址不变,retaincount+1
    NSMutableArray* arrayMCopy = [array mutableCopy];//地址改变,但是数组中成员指针和obj1相同,浅拷贝
    
    NSMutableArray* arrayM1 = [arrayMCopy Copy];//地址改变,但是数组中成员指针和obj1相同,浅拷贝。arrayM1为NSArray不可修改
    NSMutableArray* arrayM2 = [arrayMCopy mutableCopy];//地址改变,但是数组中成员指针和obj1相同,浅拷贝

    //推断  

    NSArray:
    - (id)copywithZone:(NSZone*)zone
    {
      //伪码
      return [self retain];
    }
    
    - (id)mutableCopywithZone:(NSZone*)zone
    {
      NSMutableArray* copy = [[NSMutableString alloc] initxxxxxx];
      for (id element in self) {
        [copy addObject:element];//element retian count + 1
        ....
      }
      return copy;
    }
    
    NSMutableArray:
    - (id)copywithZone:(NSZone*)zone
    {
      NSArray* copy = [[NSArray alloc] initXXX];
      /*把每个element加入到copy数组,retainCount+1*/
      ....
      return copy;
    }
    
    - (id)mutableCopywithZone:(NSZone*)zone
    {
      NSMutableArray* copy = [[NSMutableString alloc] initxxxxxx];
      for (id element in self) {
        [copy addObject:element];//element retian count + 1
        ....
      }
      return copy;
    }

    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,如:

    - (NSMutableArray *)mutableDeepCopy
    {
        NSMutableArray *ret = [[NSMutableArrayalloc] initWithCapacity:[self count]];
        for (id value in self)
        {
            id oneCopy = nil;
            if ([value respondsToSelector:@selector(mutableDeepCopy)])
                oneCopy = [value mutableDeepCopy];
            else if ([value respondsToSelector:@selector(mutableCopy)])
                oneCopy = [value mutableCopy];
            if (oneCopy == nil)
                oneCopy = [value copy];
            [ret addObject: oneCopy];
        }
        return ret;
    }

    原文地址:http://blog.csdn.net/omegayy/article/details/7311839

     
  • 相关阅读:
    独立人格,让人生更美好
    版本控制入门简介
    Android蓝牙操作
    Android Rect和RectF的区别
    做个环保主义的程序员
    java/android下JNI编程总结
    别太单纯,也别太不单纯
    C++ namespace的用法
    JNI编程
    企业架构 - 架构原则
  • 原文地址:https://www.cnblogs.com/g-ios/p/5088991.html
Copyright © 2011-2022 走看看