你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS-copy與mutableCopy淺析

iOS-copy與mutableCopy淺析

編輯:IOS開發綜合

在iOS開發中,當提到深拷貝和淺拷貝的時候,大家都說懂,簡單;都會說,淺拷貝:指針(地址)拷貝,不會產生新對象;深拷貝:內容拷貝,會產生新對象,但當問及大家copy與mutableCopy的時候,他們各自是深拷貝還是淺拷貝的時候,誰又有底氣答對呢?下面一起研究下吧


1、不可變字符串的拷貝

      NSString *string = @"string";

      NSString *str1 = [string copy];                // 沒有產生新對象 【淺拷貝】
      NSMutableString *str2 = [string mutableCopy];  // 產生新對象    【深拷貝】

      NSLog(@"%p %p %p", string, [string copy], [string mutableCopy]); 

打印結果如下:

這裡寫圖片描述

根據打印結果解析:
當不可變字符串調用copy的時候,指針地址沒有發生改變,也就意味著沒有產生新的對象,所以屬於淺拷貝;
當不可變字符串調用mutableCopy的時候,指針地址發生了改變,意味著產生新的對象,所以屬於深拷貝。


2、可變字符串的拷貝

      NSMutableString *string = [NSMutableString string];
      [string appendString:@"text1"];

      NSString *str1 = [string copy];              // 產生新對象,變為不可變字符串【深拷貝】
      NSMutableString *str2 = [string mutableCopy];// 產生新對象,還是可變字符串  【深拷貝】

      [str2 appendString:@"text2"];

      NSLog(@"%p %p %p", string, [string copy], [string mutableCopy]);
      NSLog(@"%@ %@ %@", string, str1, str2);

打印結果如下:

這裡寫圖片描述

根據打印結果解析:
當可變字符串調用copy的時候,指針地址發生了改變,也就意味著產生新的對象,所以屬於深拷貝;
當可變字符串調用mutableCopy的時候,指針地址發生了改變,意味著產生新的對象,所以屬於深拷貝。


3、不可變數組的拷貝

      NSArray *array = @[@"text1", @"text2"];

      NSArray *array1 = [array copy];               // 沒有產生新對象  【淺拷貝】

      NSMutableArray *array2 = [array mutableCopy]; // 產生新對象,變為可變數組【深拷貝】

      [array2 addObject:@"text3"];

      NSLog(@"%p %p %p", array, array1, array2);
      NSLog(@"%@ %@ %@", array, array1, array2);

打印結果如下:

這裡寫圖片描述

根據打印結果解析:
當不可變數組調用copy的時候,指針地址沒有發生改變,意味著沒有產生新的對象,所以屬於淺拷貝;
當不可變數組調用mutableCopy的時候,指針地址發生了改變,意味著產生新的對象,所以屬於深拷貝。


4、可變數組的拷貝

      NSMutableArray *mutableArray = @[@"text1", @"text2"].mutableCopy;

      NSArray *array1 = [mutableArray copy];                      // 產生新對象,變為不可變數組【深拷貝】

      NSMutableArray *mutableArray1 = [mutableArray mutableCopy]; // 產生新對象,變為可變數組  【深拷貝】

      [mutableArray1 addObject:@"text3"];

      NSLog(@"%p %p %p", mutableArray, [mutableArray copy], [mutableArray mutableCopy]);
      NSLog(@"%@ %@ %@", mutableArray, array1, mutableArray1);

打印結果如下:

這裡寫圖片描述

根據打印結果解析:
當可變數組調用copy的時候,指針地址發生了改變,也就意味著產生新的對象,所以屬於深拷貝;
當可變數組調用mutableCopy的時候,指針地址發生了改變,意味著產生新的對象,所以屬於深拷貝。


5、自定義對象的拷貝

由於自定義對象不考慮可變,所以忽略mutableCopy

首先,當對象需要調用 copy 的時候,需要遵守遵守 NSCopying 協議 和 調用 copyWithZone:這個方法

@interface Dog : NSObject
/** 姓名 */
@property (nonatomic, copy) NSString *name;
/** 年齡 */
@property (nonatomic, assign) int age;

@end


// 需要遵守 NSCopying 協議
@interface Dog () 

@end

@implementation Dog
// 當對象需要調用 copy 的時候,需要調用 copyWithZone:這個方法
- (id)copyWithZone:(NSZone *)zone
{
    Dog *dog = [[Dog allocWithZone:zone] init];
    dog.name = self.name;
    dog.age  = self.age;
    return dog;
}
@end
      Dog *dog = [[Dog alloc] init]; // [object copyWithZone:zone]
      dog.name = @"huahua";
      dog.age  = 1;

      Dog *newDog = [dog copy]; // 產生新對象【深拷貝】
      NSLog(@"%@ %@",dog,newDog);
      NSLog(@"%@ %@",dog.name,newDog.name);

打印結果如下:

這裡寫圖片描述

根據打印結果解析:
當自定義對象調用copy的時候,指針地址發生了改變,也就意味著產生新的對象,所以屬於深拷貝;


6、屬性中的copy 和 strong

在平時定義屬性的時候,對於NSString 和 block 我們經常用 copy 來修飾
數組和字典等類型用 strong 來修飾;

當使用 copy 修飾屬性的時候,屬性的setter方法會調用[object copy]產生新的對象,
這樣,當原object對象的值發生改變時,並不影響新對象值;

// 定義NSString
 @property(nonatomic, copy) NSString *name;
 .
 .
 .
// 當調用上面的copy的時候,等價於下面的代碼
- (void)setName:(NSString *)name {
      if (_name != name) {
         [_name release];
          _name = [name copy];
       }
}

當使用 strong 修飾屬性的時候,屬性的setter方法會直接強引用該對象,
這樣,當原object對象的值發生改變時,新對象的屬性也改變;
例如:我們平時使用strong修飾的NSMutableArray,這個可變數組在當前文件中只有一個,而且是可變的;

/** 數組 */
@property(nonatomic,strong)NSMutableArray *array;
.
.
.
// 當調用上面的strong的時候,等價於下面的代碼
-(void)setArray:(NSMutableArray *)array{
    _array = array;
}

以前面的自定義Dog對象進行舉例:

    // 定義一個可變的字符,作為小狗的name
    NSMutableString *dogName = [NSMutableString stringWithString:@"huahua"];   // dogName == "huahua"

    Dog *dog = [[Dog alloc] init];
    // 將字符賦值給dog的name屬性
    dog.name = dogName;
    // 當小狗的name值發生改變時
    [dogName appendString:@"lvlv"];   // dogName == "huahualvlv"
    // 小狗的名還是原來的姓名
    NSLog(@"%@",dog.name);            // 打印結果:huahua

分析:當給dog.name 賦值時,會將 [dogName copy] 後的結果賦值給 dog.name,這樣,當dogName字符的值發生改變後,不會影響 dog.name 的值;


總結:當不可變類型對象調用copy拷貝後,不會產生新的對象,屬於淺拷貝,其他類型對象不管調用copy亦或是mutableCopy,都會產生新的對象,屬於深拷貝!
這裡寫圖片描述

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved