最近有个需求需要copy数组对象才发现之前一直不太了解深浅copy就随手写了个小demo研究下。
1,NSObject中的copy和mutableCopy方法
NSString *str = @"aaaa";
NSString *copyStr = [str copy];
NSString *mutableCopyStr = [str mutableCopy];
NSLog(@"str = %p, copy = %p, mutableCopy = %p",str,copyStr,mutableCopyStr);
打印结果:str = 0x10abea068, copy = 0x10abea068, mutableCopy = 0x60400025ca70
对于NSString对象来说copy方法并没有实现深copy。( str对象和copy指向同一地址)
mutableCopy方法实现了深copy。
NSMutableString *str1 = [[NSMutableString alloc]initWithString:@"aaaa"];
NSMutableString *copy1 = [str1 copy];
NSMutableString *mutableCopy1 = [str1 mutableCopy];
NSLog(@"str1 = %p , copy = %p , mutableCopy = %p",str1,copy1,mutableCopy1);
打印结果: str1 = 0x60400025cf20 , copy = 0xa000000616161614 , mutableCopy = 0x60400025cce0
[str1 appendString:@"bbbb"];
NSLog(@"str1 = %@ , copy = %@ , mutableCopy = %@",str1, copy1,mutableCopy1);
打印结果: str1 = aaaabbbb , copy = aaaa , mutableCopy = aaaa
对于NSMutableString对象来说mutableCopy和copy都实现了深copy。
经测试NSArray,NSDictionary等对象和NSString一样copy浅copy mutableCopy深copy
NSMutableArray,NSMutableDictionary等可变对象和NSMutableString一样copy和mutableCopy实现了深copy
自定义Person类实现NSCopying协议
@interface Person : NSObject<NSCopying>
@property (strong, nonatomic) NSString *name;
@end
#import "Person.h"
@implementation Person
- (id)copyWithZone:(NSZone *)zone {
Person *p = [Person new];
p.name = _name;
return p;
}
@end
Person *p = [[Person alloc]init];
p.name= @"kk";
Person *p1 = [p copy];
p1.name = @"kkoo";
NSLog(@"p name = %@ , p1 name = %@", p.name,p1.name);
打印结果p name = kk , p1 name = kkoo
通过copy或者mutableCopy可以实现深copy
2,深copy对象数组
Person *p = [[Person alloc]init];
p.name= @"kk";
NSArray *arr = @[p];
NSArray *arr1 = [arr mutableCopy];
NSLog(@"arr = %p, arr1 = %p", arr, arr1);
打印结果:arr = 0x604000009cf0, arr1 = 0x6040004579d0。 深copy数组
Person *p_arr = arr[0];
Person *p_arr1 = arr1[0];
NSLog(@"p_arr = %p, p_arr1 = %p",p_arr,p_arr1);
打印结果:p_arr = 0x60000001f6d0, arr1 = 0x60000001f6d0
数组里面对象并没有得到深copy
此时大致能想到两种方法真正实现对象数组的深copy
第一种,重新声明一个数组对象,遍历之前的数组对象调用Person的copy方法插入新数组
NSMutableArray *arr3 = [NSMutableArray array];
for (Person *person in arr) {
Person *tmpPerson = [person copy];
[arr3 addObject:tmpPerson];
}//或者不用copy方法直接初始化新的Person对象插进数组
得到arr3实现数组对象arr的深copy
第二种,利用归档的方法重新获得数组
在Person 类中实现NSCoding协议
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_name forKey:@"name"];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
_name = [aDecoder decodeObjectForKey:@"name"];
}
return self;
}
NSArray *arr4 = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:arr]];
得到arr4实现数组对象arr的深copy