您的位置:首页 > 移动开发 > IOS开发

iOS 对象数组的深拷贝(NSCoding协议)

2017-07-11 14:29 183 查看
项目过程中遇到了对象数组的使用:联系人界面——需要分区显示,如果我存放在一个数组然后每次显示都重新分组发现会有一个计算的延迟,所有我先进行分区放在了一个单例类中的字典中。当我需要用到这个联系人的界面额外定义一个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);


输出结果Person的name却是c

有人说如果要想深拷贝数组中的对象就必须重新建立一个数组,然后在循环的时候给新数组即:

Person *person1 = [[Person alloc] init];
person1.name = @"a";

NSArray *array1 = [NSArray arrayWithObjects:person1, nil];

NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:0];
[array1 enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
Person *person = [obj copy];
person.name = @"c";
[arrayM addObject:person];
}];

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协议也可以实现深拷贝。后来我就放弃了把联系人放在单例类中,直接放在了本地文件中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息