iOS-深淺拷貝

首先關於copy和mutableCopy的行爲:無論是NSString這種元素類、仍是NSArray這樣的容器類、仍是Mutable和非Mutable類,copy和mutableCopy調用後表現的行爲究竟是什麼樣完成取決於類自己NSCopying和NSMutableCopying協議是如何實現的。數組

想要正常調用copy和mutableCopy兩個函數,那麼類就必定要實現對應的協議。函數

1.  元素數據的copy和mutableCopy。spa

經常使用的NSString類,示例代碼以下:.net

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。code

經常使用類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相同,淺拷貝

 

//推斷  blog

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.   深拷貝內存

上面提到的官方文檔中介紹兩種實現深拷貝的方法:ci

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

相關文章
相關標籤/搜索