iOS深复制与浅复制

一、概念:

浅复制,也有人称做浅拷贝。就是只改变新对象的指针指向,并未生成新的内存地址,只是将新对象的指针指向要复制对象的内存地址。集合类与非集合类执行copy操作都是浅复制。

深复制,同样也有人称做深拷贝。即改变新对象指针指向,还为对象生成新的内存地址。深复制又分为单层深复制与完全深复制,单层深复制虽然生成了新的内存地址,但是新的对象中的元素地址还是旧对象元素的地址;完全深复制就不一样了,不仅内存地址是新的,对象里面的元素地址也是新的。

 

二、非集合类对象:

1. 非集合类的copy操作:

NSString* stringHello = @"hello";
NSString* stringCopy = [stringHello copy];
NSLog(@"当前地址:%p---%p", stringHello, stringCopy); // 当前地址:0x104e9e288---0x104e9e288

NSMutableString* stringMu = [NSMutableString stringWithString:@"hello"];
NSString* stringMuCopy = [stringMu copy]; // 注意:copy产生新对象是NSString不是NSMutableString类型,切勿当做NSMutableString类型进行相关操作,不然会crash!
NSLog(@"当前地址:%p---%p", stringMu, stringMuCopy); // 当前地址:0x6040002566b0---0xa00006f6c6c65685

综上可得:

1. NSString类型的copy操作生成的新对象只是指向了旧对象的内存地址,并未产生新的内存地址,即进行了浅复制。

2. NSMutableString类型的copy操作产生新的内存地址生成NSString类型的对象,即进行了深复制。

2、非集合类的mutableCopy操作:

NSString* string = @"hello";
NSMutableString* muStr = [NSMutableString stringWithString:@"mjz"];
    
/** mutableCopy  **/
NSMutableString* stringMuCopy = [string mutableCopy];
NSMutableString* muStringMuCopy = [muStr mutableCopy];
 
/** appendString拼接字符串  **/  
[stringMuCopy appendString:@"jj"];
[muStringMuCopy appendString:@"zz"];

/**
  * 打印结果:
  * 地址1:string: 0x1046d10e8 , stringMuCopy :0x60c000056c80
  * 地址2:muStr: 0x60c000056950 , muStringMuCopy :0x60c000055ea0
**/
NSLog(@"地址1:string: %p , stringMuCopy :%p", string, stringMuCopy);
NSLog(@"地址2:muStr: %p , muStringMuCopy :%p", muStr, muStringMuCopy);

综上可得NSString与NSMutableString的mutableCopy操作都是深复制,产生新对象。

三、集合类对象:

1. 集合类的copy操作:

NSArray* array = @[@"jj", @"zz"];
NSArray* arrayCopy = [array copy];
NSLog(@"array:%p", array);
NSLog(@"arrayCopy:%p", arrayCopy);
    
NSMutableArray* muArray = [NSMutableArray arrayWithObjects:@"mm", @"jj", @"zz", nil];
NSArray* muArrayCopy = [muArray copy];
[muArray addObject:@"123"];
//    [muArrayCopy addObject:@"123"]; // 崩溃,muArrayCopy为NSArray类型不是NSMutableArray类型
NSLog(@"muArray:%p", muArray);
NSLog(@"muArrayCopy:%p", muArrayCopy);

/* 打印结果:
   array:0x604000032700
   arrayCopy:0x604000032700
   muArray:0x6000002585d0
   muArrayCopy:0x600000258870
*/

综上可得:集合类的copy操作与非集合类copy操作基本一致,NSArray的copy操作是浅复制,NSMutableArray的copy操作是深复制。

2. 集合类的mutableCopy操作:

NSArray* array = @[@"mm", @"jj"];
NSMutableArray* arrayMuCopy = [array mutableCopy];
[arrayMuCopy addObject:@"hello"];
    
NSLog(@"array:%p", array);
NSLog(@"muArray:%p", arrayMuCopy);
    
NSMutableArray* muArray = [NSMutableArray arrayWithObjects:@"mm", @"jj", @"zz", nil];
NSMutableArray* muArrayMuCopy = [muArray mutableCopy];
[muArray addObject:@"tt"];
[muArrayMuCopy addObject:@"yy"];
    
NSLog(@"muArrayNew:%p", muArray);
NSLog(@"muArrayMuCopy:%p", muArrayMuCopy);

/* 打印结果:
  array:0x60c000223540
  muArray:0x60c0002403f0
  muArrayNew:0x60400024c9c0
  muArrayMuCopy:0x60400024cd80
*/

综上可得:集合类的copy操作与非集合类mutableCopy操作基本一致,都是深复制。

四、单层深复制

 简述:以上的深复制只是产生了新的内存地址,但对象中的元素地址还是旧对象的地址。

NSArray* array = [NSArray arrayWithObject:@"hello"];
//    NSMutableArray* array = [NSMutableArray arrayWithObject:@"hello"]; // 可开启调试NSMutableArray类型
NSArray* arrayCopy = [array copy];
NSMutableArray* arrayMu = [array mutableCopy];

NSString* stringElement = [array lastObject];
NSLog(@"对象元素地址1:%p---%p", array, stringElement);
    
NSString* stringCopyElement = [arrayCopy lastObject];
NSLog(@"对象元素地址2:%p---%p", arrayCopy, stringCopyElement);
    
NSString* stringMuElement = [arrayMu lastObject];
NSLog(@"对象元素地址3:%p---%p", arrayMu, stringMuElement);

/* 打印结果:
 * 对象元素地址1:0x6040000179f0---0x10f4f60e8
 * 对象元素地址2:0x6040000179f0---0x10f4f60e8
 * 对象元素地址3:0x604000049db0---0x10f4f60e8
 */

综上可得:集合中元素地址并未发生变化。这里只测试集合类的测试,非集合类测试一样,所以不做赘述。

五、对象的复制

简述:要实现自定义对象的复制,需要遵守NSCopying,NSMutableCopying这两个协议,并实现copyWithZone与mutableCopyWithZone这两个方法。不过此复制也是单层深复制,要进行完全深复制,可进行归档解档实现,具体代码我写在一个类里。

@interface JZPerson : NSObject<NSCopying, NSMutableCopying, NSCoding>
@property (copy, nonatomic) NSString* name;
@property (copy, nonatomic) NSString* age;
@end


#import "JZPerson.h"
@implementation JZPerson

#pragma mark 复制实现
- (id)copyWithZone:(NSZone *)zone {
    JZPerson* personObj = [[JZPerson allocWithZone:zone] init];
    personObj.name = self.name;
    personObj.age = self.age;
    return personObj;
}

- (id)mutableCopyWithZone:(NSZone *)zone {
    JZPerson* personObj = [[JZPerson allocWithZone:zone] init];
    personObj.name = self.name;
    personObj.age = self.age;
    return personObj;
}

#pragma mark 解档与归档
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeObject:self.age forKey:@"age"];
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.age = [aDecoder decodeObjectForKey:@"age"];
    }
    return self;
}

@end


/** 测试代码  **/
JZPerson* person = [[JZPerson alloc] init];
person.name = @"tsy";
person.age = @"11";
    
JZPerson* personCopy = [person copy];
JZPerson* personMuCopy = [person mutableCopy];
    
NSLog(@"%p---%p--%p", person, person.name, person.age);
NSLog(@"%p---%p--%p", personCopy, personCopy.name, personCopy.age);
NSLog(@"%p---%p--%p", personMuCopy, personMuCopy.name, personMuCopy.age);
    
JZPerson *personDeepCopy = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:person]];
NSLog(@"%p---%p--%p", personDeepCopy, personDeepCopy.name, personDeepCopy.age);


/* 打印结果:
 * person:0x608000229460---0x10de0f548--0x10de0f208
 * personCopy:0x608000229400---0x10de0f548--0x10de0f208
 * personMuCopy:0x6080002294c0---0x10de0f548--0x10de0f208
 * personDeepCopy:0x608000229420---0xa000000007973743--0xa000000000031312
 */

六、结论

1、不可变的集合类与非集合类的copy是浅复制,而mutableCopy则是深复制;

2、可变的集合类与非集合类的copy与mutableCopy都是深复制;

3、自定义对象复制为深复制,归档与解档可实现完全深复制。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值