// 不可变容器
- (void)test {
NSString *str = @"hello";
NSArray *arr1 = [NSArray arrayWithObjects:str, nil];
NSLog(@"%p--%p", arr1, arr1[0]);
NSArray *arr2 = [arr1 copy];
NSLog(@"%p--%p", arr2, arr2[0]); //不可变对象copy, 浅拷贝
NSMutableArray *mutableArr3 = [arr1 mutableCopy];
NSLog(@"%p--%p", mutableArr3, mutableArr3[0]); //不可变对象mutableCopy, 深拷贝(非完全拷贝,数组中元素的地址并没有改变,仅拷贝了数组本身)
// 2020-03-13 15:29:03.204397+0800 LearnBase[87886:37461358] 0x1007b96f0--0x100002060
// 2020-03-13 15:29:03.204912+0800 LearnBase[87886:37461358] 0x1007b96f0--0x100002060
// 2020-03-13 15:29:03.204976+0800 LearnBase[87886:37461358] 0x103200890--0x100002060
}
// 可变容器
- (void)test1 {
NSString *str = @"hello";
NSMutableArray *arr1 = [NSMutableArray arrayWithObjects:str, nil];
NSLog(@"%p--%p", arr1, arr1[0]);
NSArray *arr2 = [arr1 copy]; // 深拷贝(非完全拷贝)
NSLog(@"%p--%p", arr2, arr2[0]);
NSMutableArray *arr3 = [arr1 mutableCopy]; // 深拷贝(非完全拷贝)
NSLog(@"%p--%p", arr3, arr3[0]);
// 2020-03-13 15:34:31.302249+0800 LearnBase[89027:37468521] 0x10079dc60--0x100002060
// 2020-03-13 15:34:31.302811+0800 LearnBase[89027:37468521] 0x10078fa20--0x100002060
// 2020-03-13 15:34:31.302863+0800 LearnBase[89027:37468521] 0x10079e760--0x100002060
}
//拷贝数组中元素
- (void)test2 {
NSMutableString *str = [NSMutableString stringWithFormat:@"hello"];
NSMutableDictionary *dict = [NSMutableDictionary new];
[dict setValue:str forKey:@"key1"];
// 将字典存入数组
NSMutableArray *arr1 = [NSMutableArray arrayWithObject:dict];
// 用旧数组生成新数组
NSMutableArray *arr2 = [NSMutableArray arrayWithArray:arr1]; // 深拷贝,数组内容指向没有变
NSArray *arr3 = [arr1 copy]; // arr3中dict仍指向原dict
// 使用copyItems拷贝数组元素
NSMutableArray *arr4 = [[NSMutableArray alloc] initWithArray:arr1 copyItems:YES];
// 一层深拷贝(比上面说的深拷贝多拷贝一层),拷贝了arr1中的dict, 但dict中的str仍与原来指向相同
// 把数组归档为一个NSData,再解档,实现完全深拷贝
NSData *data = [NSArchiver archivedDataWithRootObject:arr1];
NSMutableArray *arr5 = [NSUnarchiver unarchiveObjectWithData:data];
// 向字典中加入新值
[dict setValue:@"jack" forKey:@"key2"];
// 修改str
[str appendString:@" world"];
NSLog(@"%@", arr1);
NSLog(@"%@", arr2);
NSLog(@"%@", arr3);
NSLog(@"%@", arr4);
NSLog(@"%@", arr5);
NSLog(@"%p--%p--%p", arr1, arr1[0], arr1[0][@"key1"]);
NSLog(@"%p--%p--%p", arr2, arr2[0], arr2[0][@"key1"]);
NSLog(@"%p--%p--%p", arr3, arr3[0], arr3[0][@"key1"]);
NSLog(@"%p--%p--%p", arr4, arr4[0], arr4[0][@"key1"]);
NSLog(@"%p--%p--%p", arr5, arr5[0], arr5[0][@"key1"]);
// 2020-03-13 16:36:08.740332+0800 LearnBase[1914:37550166] (
// {
// key1 = "hello world";
// key2 = jack;
// }
// )
// 2020-03-13 16:36:08.740931+0800 LearnBase[1914:37550166] (
// {
// key1 = "hello world";
// key2 = jack;
// }
// )
// 2020-03-13 16:36:08.741103+0800 LearnBase[1914:37550166] (
// {
// key1 = "hello world";
// key2 = jack;
// }
// )
// 2020-03-13 16:36:08.741174+0800 LearnBase[1914:37550166] (
// {
// key1 = "hello world";
// }
// )
// 2020-03-13 16:36:08.741233+0800 LearnBase[1914:37550166] (
// {
// key1 = hello;
// }
// )
// 2020-03-13 16:36:08.741267+0800 LearnBase[1914:37550166] 0x1007772d0--0x1007770a0--0x100777070
// 2020-03-13 16:36:08.741300+0800 LearnBase[1914:37550166] 0x1007773c0--0x1007770a0--0x100777070
// 2020-03-13 16:36:08.741333+0800 LearnBase[1914:37550166] 0x100768e70--0x1007770a0--0x100777070
// 2020-03-13 16:36:08.741361+0800 LearnBase[1914:37550166] 0x1007775d0--0x1007775b0--0x100777070
// 2020-03-13 16:36:08.741387+0800 LearnBase[1914:37550166] 0x100775030--0x100774af0--0x100774550
}
值得注意,关于可变容器对象与不可变容器对象定义时属性修饰:
@interface CopyAndMutableCopy ()
@property (nonatomic, strong) NSArray *arr1;
@property (nonatomic, copy) NSMutableArray *arr2;
@end
@implementation CopyAndMutableCopy
- (void)test3 {
NSMutableArray *mutableArr = [NSMutableArray array];
self.arr1 = mutableArr; // 如果NSArray在定义时使用strong修饰,调用set方法时不会产生深拷贝,则会出现以下情况, 因此应该使用copy修饰
[mutableArr addObject:@"hello"];
NSLog(@"%@", self.arr1);
// 2020-03-13 16:49:13.878240+0800 LearnBase[4620:37567082] (
// hello
// )
self.arr2 = mutableArr; //如果NSMutableArray在定义时使用copy修饰,调用set方法会产生一个不可变的对象,因此会出现以下情况, 因此应该使用strong修饰
[self.arr2 addObject:@"world"]; // unrecognized selector sent to instance 0x1024002f0
NSLog(@"%@", self.arr2);
}
当然,我们也不会在使用时容器间直接调用setter赋值。