写在前面
项目过程中遇到了对象数组的使用:联系人界面——需要分区显示,如果我存放在一个数组然后每次显示都重新分组发现会有一个计算的延迟,所有我先进行分区放在了一个单例类中的字典中。当我需要用到这个联系人的界面额外定义一个NSDictionary对它赋值,试图修改NSDictionary时发现存放在单例类中的数组对象也被修改了。感觉很无语啊。当时我的嵌套是这样的
NSDictionary@{key1:NSMutableArray@[对象1,对象2],key2:NSMutableArray@[对象3,对象4],...}
就是在一个单例类中定义了一个不可变字典NSDictionary的属性,存放了n个可变数组NSMutableArray,而这些可变数组可以动态增加或者删除数组内存放的对象。
在网上看了很多对象的深拷贝,浅拷贝copy/mutableCopy。并且我已经实现了NSCoding协议。可是发现全部无效。于是我写了一个Test工程发现一个问题
NSArray *array1 = [NSArray arrayWithObjects:@"a", nil];
NSMutableArray *arry2 = [array1 mutableCopy];
[arry2 replaceObjectAtIndex:0 withObject:@"b"];
NSLog(@"%@",array1);
这样输出结果依然是@[a]
但是当我定义两个一个实现了NSCoding协议并且有一个name属性的Person对象并且放到数组中时
Person *person1 = [[Person alloc] init];
person1.name = @"a";
NSArray *array1 = [NSArray arrayWithObjects:person1, nil];
NSArray *arry2 = [NSArray arrayWithArray:array1];
[arry2 enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
Person *person = obj;
person.name = @"c";
}];
NSLog(@"%@",array1);
并且遍历的时候对象必须copy,不然还是难以达到深拷贝。
后来找到另一种方法,就是通过[NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:]];
Person *person1 = [[Person alloc] init];
person1.name = @"a";
Person *person2 = [[Person alloc] init];
person2.name = @"b";
NSArray *array1 = [NSArray arrayWithObjects:person1, nil];
NSArray *array2 = [NSArray arrayWithObjects:person2, nil];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:array1,@"a",array2,@"b", nil];
[Object shareObject].dict = dict;
NSLog(@"1:%@",[Object shareObject].dict);
NSDictionary *temDict = [[Object shareObject].dict mutableCopy];
NSMutableArray *arrayM = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:[temDict objectForKey:@"a"]]];
[arrayM enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
Person *person = obj;
person.name = @"c";
}];
NSLog(@"2:%@",[Object shareObject].dict);
并且不管你嵌套了多少层,只要每一层都实现了NSCoding协议也可以实现深拷贝。后来我就放弃了把联系人放在单例类中,直接放在了本地文件中。