前言
上周说了一下[iOS开发]关于copy属性的一个细节点,说的是copy属性的作用以及在重写copy属性的setter方法的时候需要注意的细节,如果读者有兴趣可以会看这篇,本文将在上一篇的基础上来看一个实际开发中的copy注意点.
开发案例
网络请求基本是移动开发必不可少的一部分了,关于网络请求返回的数据(通常是json),我们通常是先进行解析再对其进行模型的封装,曾经在这个地方我遇到过一个可爱的问题.
当时我需要对一个网络请求返回的数据A,在B和C两处分别进行使用,那copy方法是没跑了
Student *s1 = ({
Student *student = [[Student alloc] init];
student.name = @"s1";
student.score = 100;
student;
});
Student *s2 = ({
Student *student = [[Student alloc] init];
student.name = @"s2";
student.score = 90;
student;
});
NSMutableArray *array_m = [NSMutableArray arrayWithObjects:s1,s2,nil];
NSArray *array = [array_m copy];
NSArray *array2 = [array_m copy];
({ })是GCC写法我在之前写的[iOS开发]方法的封装之链式编程也使用过,别看书写起来行数可能更多,可是复用性和阅读便利性可是杠杠的.
先介绍一下Student这个类
#import
@interface Student : NSObject
@property (nonatomic, assign) NSUInteger score;
@property (nonatomic, copy) NSString *name;
@end
array_m是自己处理好的模型数组(处理时肯定是可变数组),在我们使用这些数据的时候一般我们都是得到一个不可变的模型数组,此时需要对处理后的模型数组进行copy得出不可变数组.
之前我说了这是一个可爱的错误,为什么可爱呢,请看
array[0].name = @"xxx";
NSLog(@"array2[0].name = %@",array2[0].name);
输出结果是
array2[0].name = xxx
这里打印一下两个数组的地址
NSLog(@"arrayP = %p",array);
NSLog(@"array2P = %p",array2);
地址结果是
arrayP = 0x600000026c40
array2P = 0x600000026c60
说明copy成功了,这确实是两个不同的数组,在这一瞬间思路感觉都要断了.......................
可爱的自己
谁说过对数组进行copy里面元素也会自行copy的?简直是自己一厢情愿,打印一下看看咯
NSLog(@"array[0]P = %p",array[0]);
NSLog(@"array2[0]P = %p",array2[0]);
真是可爱^ ^
array[0]P = 0x610000023920
array2[0]P = 0x610000023920
此刻我们还需要对数组中的每一个元素进行copy
NSMutableArray *arrayM = ({
NSMutableArray *mutableArray = [NSMutableArray array];
for (Student *stu in array_m) {
Student *newStu = [stu copy];
[mutableArray addObject:newStu];
}
mutableArray;
});
NSMutableArray *arrayM2 = ({
NSMutableArray *mutableArray = [NSMutableArray array];
for (Student *stu in array_m) {
Student *newStu = [stu copy];
[mutableArray addObject:newStu];
}
mutableArray;
});
NSArray *array = [arrayM copy];
NSArray *array2 = [arrayM2 copy];
得出最终两个名叫array和array2的可变数组
这里注意要让Student这个类遵守NSCopying协议,并实现copyWithZone方法
//深拷贝为了得到地址不同的数据,因为有两个地方要用到
- (id)copyWithZone:(NSZone *)zone{
Student *student=[[[self class] allocWithZone:zone] init];
student.name=[_name copy]; //深拷贝
//score属性是基本数据类型不需拷贝
return student;
}
这里要注意的是如果Student的属性中还有其他的自定义对象,如需进行复制,请为其实现copyWithZone方法
这样在之后你会发现array和array2才是内容相同地址空间根本不同的两个数组.在你任意使用其中一组数据的时候不会影响到另一组数据.
这种可爱的错误可别犯第二次
版权声明:本文版权归本文作者所有,始发于,如需转载请联系作者,违者必究.