OC的深拷贝与浅拷贝

2020-05-08  本文已影响0人  苏沫离

Objective-C 对象是通过指向该对象内存地址的指针,以间接方式访问的。

指针赋值:

对于实现了NSCopying与NSMutableCopying协议的对象来说,指针赋值并非简单的赋值,还有额外的操作:

2、非容器类与容器类

2.1、非容器类 NSString

系统类 NSString 实现了 NSCopyingNSMutableCopying 协议

2.1.1、不可变对象 NSString
{
    NSString *string = [[NSString alloc] initWithString:@"String"];
    NSString *string_1 = string;
    NSString *string_2 = [string copy];
    NSString *string_3 = [string mutableCopy];
    NSLog(@"string     : %@",logString(string));
    NSLog(@"string_1   : %@",logString(string_1));
    NSLog(@"string_2   : %@",logString(string_2));
    NSLog(@"string_3   : %@",logString(string_3));
}

/** 打印日志
string     : String  0x1070701a8 |  rCount :-1 | __NSCFConstantString
string_1   : String  0x1070701a8 |  rCount :-1 | __NSCFConstantString
string_2   : String  0x1070701a8 |  rCount :-1 | __NSCFConstantString
string_3   : String  0x600003f381e0 |  rCount :1 | __NSCFString
 */
2.1.2、可变对象 NSMutableString
{
    NSMutableString *mString = [[NSMutableString alloc] initWithString:@"Mutable String"];
    NSString *mString_1 = mString;
    NSString *mString_2 = [mString copy];
    NSString *mString_3 = [mString mutableCopy];
    NSLog(@"mString     : %@",logString(mString));
    NSLog(@"mString_1   : %@",logString(mString_1));
    NSLog(@"mString_2   : %@",logString(mString_2));
    NSLog(@"mString_3   : %@",logString(mString_3));
}
/** 打印日志
mString     : Mutable String  0x600003f10840 |  rCount :1 | __NSCFString
mString_1   : Mutable String  0x600003f10840 |  rCount :1 | __NSCFString
mString_2   : Mutable String  0x60000316d420 |  rCount :1 | __NSCFString
mString_3   : Mutable String  0x600003f12160 |  rCount :1 | __NSCFString
 */
操作 非容器类 NSString NSMutableString
copy 类似于ARC下的指针赋值 深拷贝,得到一个可变对象
mutableCopy 深拷贝,得到一个可变对象 深拷贝,得到一个可变对象
2.2、容器类 NSArrayNSDictionary
2.2.1、容器类 NSArray
{
    NSString *string = @"String";
    NSMutableString *mString = [[NSMutableString alloc] initWithString:@"Mutable String"];
    NSLog(@"string  :  %@",logString(string));
    NSLog(@"mString :  %@",logString(mString));
    
    NSArray *array = [[NSArray alloc] initWithObjects:string,mString, nil];
    NSMutableArray *mArray = [[NSMutableArray alloc] initWithObjects:string,mString, nil];
    
    mString.string = @"Mutable String_2";
    NSLog(@"mString :  %@",logString(mString));
    
    NSArray *array_1 = array;
    NSArray *array_2 = [array copy];
    NSArray *array_3 = [array mutableCopy];
    NSLog(@"array     : %@",logArray(array));
    NSLog(@"array_1   : %@",logArray(array_1));
    NSLog(@"array_2   : %@",logArray(array_2));
    NSLog(@"array_3   : %@",logArray(array_3));
    
    printf("\n  \n");
    NSMutableArray *mArray_1 = mArray;
    NSMutableArray *mArray_2 = [mArray copy];
    NSMutableArray *mArray_3 = [mArray mutableCopy];
    NSLog(@"mArray     : %@",logArray(mArray));
    NSLog(@"mArray_1   : %@",logArray(mArray_1));
    NSLog(@"mArray_2   : %@",logArray(mArray_2));
    NSLog(@"mArray_3   : %@",logArray(mArray_3));
}
/** 打印日志:
string  :  String  0x10aa001a8 |  rCount :-1 | __NSCFConstantString
mString :  Mutable String  0x600002c4e550 |  rCount :1 | __NSCFString
mString :  Mutable String_2  0x600002c4e550 |  rCount :3 | __NSCFString
array     :
      String :0x10aa001a8
      Mutable String_2 :0x600002c4e550
  0x6000022485e0 | rCount :2 | __NSArrayI
array_1   :
      String :0x10aa001a8
      Mutable String_2 :0x600002c4e550
  0x6000022485e0 | rCount :2 | __NSArrayI
array_2   :
      String :0x10aa001a8
      Mutable String_2 :0x600002c4e550
  0x6000022485e0 | rCount :2 | __NSArrayI
array_3   :
      String :0x10aa001a8
      Mutable String_2 :0x600002c4e550
  0x600002c463d0 | rCount :1 | __NSArrayM

  
mArray     :
      String :0x10aa001a8
      Mutable String_2 :0x600002c4e550
  0x600002c44000 | rCount :1 | __NSArrayM
mArray_1   :
      String :0x10aa001a8
      Mutable String_2 :0x600002c4e550
  0x600002c44000 | rCount :1 | __NSArrayM
mArray_2   :
      String :0x10aa001a8
      Mutable String_2 :0x600002c4e550
  0x6000022408c0 | rCount :1 | __NSArrayI
mArray_3   :
      String :0x10aa001a8
      Mutable String_2 :0x600002c4e550
  0x600002c78ff0 | rCount :1 | __NSArrayM
*/
2.2.2、容器类NSDictionary
{
    NSString *string = @"String";
    NSMutableString *mString = [[NSMutableString alloc] initWithString:@"Mutable String"];
    NSLog(@"string  :  %@",logString(string));
    NSLog(@"mString :  %@",logString(mString));
    
    NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:string,@"NSString",mString,@"NSMutableString", nil];
    NSMutableDictionary *mDict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:string,@"NSString",mString,@"NSMutableString", nil];
    
    NSDictionary *dict_1 = dict;
    NSDictionary *dict_2 = [dict copy];
    NSDictionary *dict_3 = [dict mutableCopy];
    NSLog(@"dict    : %@",logDictionary(dict));
    NSLog(@"dict_1  : %@",logDictionary(dict_1));
    NSLog(@"dict_2  : %@",logDictionary(dict_2));
    NSLog(@"dict_3  : %@",logDictionary(dict_3));
    
    printf("\n  \n");
    NSMutableDictionary *mDict_1 = mDict;
    NSMutableDictionary *mDict_2 = [mDict copy];
    NSMutableDictionary *mDict_3 = [mDict mutableCopy];
    NSLog(@"mDict    : %@",logDictionary(mDict));
    NSLog(@"mDict_1  : %@",logDictionary(mDict_1));
    NSLog(@"mDict_2  : %@",logDictionary(mDict_2));
    NSLog(@"mDict_3  : %@",logDictionary(mDict_3));
}

/** 打印日志
string  :  String  0x10fba11a8 |  rCount :-1 | __NSCFConstantString
mString :  Mutable String  0x600003859f20 |  rCount :1 | __NSCFString
dict    :
    NSString String :0x10fba11a8
    NSMutableString Mutable String :0x600003859f20
   0x600002360700 | rCount :2 | __NSDictionaryI
dict_1  :
    NSString String :0x10fba11a8
    NSMutableString Mutable String :0x600003859f20
   0x600002360700 | rCount :2 | __NSDictionaryI
dict_2  :
    NSString String :0x10fba11a8
    NSMutableString Mutable String :0x600003859f20
   0x600002360700 | rCount :2 | __NSDictionaryI
dict_3  :
    NSString String :0x10fba11a8
    NSMutableString Mutable String :0x600003859f20
   0x600003611da0 | rCount :1 | __NSDictionaryM
   
mDict    :
    NSString String :0x10fba11a8
    NSMutableString Mutable String :0x600003859f20
   0x600003611600 | rCount :1 | __NSDictionaryM
mDict_1  :
    NSString String :0x10fba11a8
    NSMutableString Mutable String :0x600003859f20
   0x600003611600 | rCount :1 | __NSDictionaryM
mDict_2  :
    NSString String :0x10fba11a8
    NSMutableString Mutable String :0x600003859f20
   0x600003650860 | rCount :1 | __NSFrozenDictionaryM
mDict_3  :
    NSString String :0x10fba11a8
    NSMutableString Mutable String :0x600003859f20
   0x600003650800 | rCount :1 | __NSDictionaryM
 */
操作 NSArrayNSDictionary NSMutableArrayNSMutableDictionary 容器中元素
copy 浅拷贝,类似于ARC下的指针赋值 深拷贝,得到一个不可变对象 浅拷贝
mutableCopy 深拷贝,得到一个可变对象 深拷贝,得到一个可变对象 浅拷贝

3、NSString 类型的属性修饰符

什么时候使用 copy 修饰 NSString 类型的属性?什么时候使用 strong 修饰 NSString 类型的属性?

@property (nonatomic ,strong) NSString *sString;
@property (nonatomic ,copy) NSString *cString;

3.1、赋值NSMutableString常量

{
    NSMutableString *mString = [[NSMutableString alloc] initWithString:@"Mutable String"];
    self.sString = mString;
    self.cString = mString;
    NSLog(@"mString   : %@ : %p : %p : %ld",mString,mString,&mString,mString.retainCount);
    NSLog(@"sString   : %@ : %p : %p : %ld",self.sString,self.sString,&_sString,_sString.retainCount);
    NSLog(@"cString   : %@ : %p : %p : %ld",self.cString,self.cString,&_cString,_cString.retainCount);
    
    mString.string = @"Mutable String_1";
    NSLog(@"mString   : %@ : %p : %p : %ld",mString,mString,&mString,mString.retainCount);
    NSLog(@"sString   : %@ : %p : %p : %ld",self.sString,self.sString,&_sString,_sString.retainCount);
    NSLog(@"cString   : %@ : %p : %p : %ld",self.cString,self.cString,&_cString,_cString.retainCount);
    
    mString = [[NSMutableString alloc] initWithString:@"Mutable String_2"];
    NSLog(@"mString   : %@ : %p : %p : %ld",mString,mString,&mString,mString.retainCount);
    NSLog(@"sString   : %@ : %p : %p : %ld",self.sString,self.sString,&_sString,_sString.retainCount);
    NSLog(@"cString   : %@ : %p : %p : %ld",self.cString,self.cString,&_cString,_cString.retainCount);    
}

/** 打印日志
mString   : Mutable String : 0x600002f19650 : 0x7ffee5f1a138 : 2
sString   : Mutable String : 0x600002f19650 : 0x7fad5cf0d800 : 2
cString   : Mutable String : 0x600002135d40 : 0x7fad5cf0d808 : 1

mString   : Mutable String_1 : 0x600002f19650 : 0x7ffee5f1a138 : 2
sString   : Mutable String_1 : 0x600002f19650 : 0x7fad5cf0d800 : 2
cString   : Mutable String : 0x600002135d40 : 0x7fad5cf0d808 : 1

mString   : Mutable String_2 : 0x600002f0c1b0 : 0x7ffee5f1a138 : 1
sString   : Mutable String_1 : 0x600002f19650 : 0x7fad5cf0d800 : 2
cString   : Mutable String : 0x600002135d40 : 0x7fad5cf0d808 : 1
 */

NSMutableString *mString 赋值给上述属性 cStringsString

改变 mString.string 的值:

mString 指向别处:

3.2、赋值NSString常量

{        
    NSString *string = @"Hello Word!";
    self.sString = string;
    self.cString = string;
    NSLog(@"string   : %@ : %p : %p : %ld",string,string,&string,string.retainCount);
    NSLog(@"sString   : %@ : %p : %p : %ld",self.sString,self.sString,&_sString,_sString.retainCount);
    NSLog(@"cString   : %@ : %p : %p : %ld",self.cString,self.cString,&_cString,_cString.retainCount);
        
    string = @"hehe";
    NSLog(@"string   : %@ : %p : %p : %ld",string,string,&string,string.retainCount);
    NSLog(@"sString   : %@ : %p : %p : %ld",self.sString,self.sString,&_sString,_sString.retainCount);
    NSLog(@"cString   : %@ : %p : %p : %ld",self.cString,self.cString,&_cString,_cString.retainCount);
}

/** 打印日志
string   : Hello Word! : 0x109ce5608 : 0x7ffee5f1a130 : -1
sString   : Hello Word! : 0x109ce5608 : 0x7fad5cf0d800 : -1
cString   : Hello Word! : 0x109ce5608 : 0x7fad5cf0d808 : -1

string   : hehe : 0x109ce5648 : 0x7ffee5f1a130 : -1
sString   : Hello Word! : 0x109ce5608 : 0x7fad5cf0d800 : -1
cString   : Hello Word! : 0x109ce5608 : 0x7fad5cf0d808 : -1
 */

NSString *string 赋值给上述属性 cStringsString:都是浅拷贝,类似于 retain 操作,引用计数 +1;
改变变量 string 的值,即将指针 string 指向别的内存地址;此时变量cStringsString 指向原有内存,值不改变;

结论:

Demo

上一篇下一篇

猜你喜欢

热点阅读