iOS开发之:copy和mutableCopy
前几天面试被问到copy和mutableCopy的知识,一开始答得是对的,但是被面试官饶了几圈就有点懵了,因为对方问的问题虽然表述不一样,但是后面问的问题在我感觉已经和前面的重复了两三次了,所以回答的时候有些犹豫,有些怀疑是不是自己没听明白对方的意思,然后就没跟上对方的节奏懵了😂
大篇幅的理论我没有时间去写,所以就简单写了点代码来测试下copy和mutableCopy的各种情况,如果有不对的或者不全的地方请大神指正!🙏
为了简单我只以NSArray和NSMutableArray为例来说明
第一种:copy方法,NSArray赋值
NSArray *array = [[NSArray alloc]init];
NSMutableArray *mutableArray = [[NSMutableArray alloc]init];
NSArray *baseArray = [NSArray arrayWithObjects:@"aaaaa", @"bbbb", @"ccccc", @"Block", nil];
array = [baseArray copy];
mutableArray = [baseArray copy];
NSLog(@"origin array: %p, %p, %@",baseArray, &baseArray, baseArray);
NSLog(@"copy array: %p, %p, %@",array, &array, array);
NSLog(@"copy mutableArray: %p, %p, %@", mutableArray, &mutableArray, mutableArray);
[mutableArray removeObjectAtIndex:0];
运行时我打了断点然后po了一下baseArray、array和mutableArray的class,如下是打印出的结果:
(lldb) po baseArray.class
__NSArrayI
(lldb) po array.class
__NSArrayI
(lldb) po mutableArray.class
__NSArrayI
可以看到,三者class类型都是__NSArrayI,mutableArray可变数组在经过copy方法后变成了不可变数组
origin array: 0x600000057df0, 0x7fff51719bd0, (
aaaaa,
bbbb,
ccccc,
Block
)
copy array: 0x600000057df0, 0x7fff51719be0, (
aaaaa,
bbbb,
ccccc,
Block
)
copy mutableArray: 0x600000057df0, 0x7fff51719bd8, (
aaaaa,
bbbb,
ccccc,
Block
)
可以看到,三者指向的地址是一样的
-[__NSArrayI removeObjectAtIndex:]: unrecognized selector sent to instance 0x60000005de20
也证明了mutableArray确实变成了不可变数组
*小结:用copy方法时,如果被copy对象为不可变类型,此时为浅拷贝,被赋值对象无论是否可变都将变为不可变对象
第二种:copy方法,NSMutableArray赋值
在.m文件中将
NSArray *baseArray = [NSArray arrayWithObjects:@"aaaaa", @"bbbb", @"ccccc", @"Block", nil];
改为:
NSMutableArray *baseArray = [NSMutableArray arrayWithObjects:@"aaaaa", @"bbbb", @"ccccc", @"Block", nil];
其他保持不变,我们继续运行,同样po一下:
(lldb) po baseArray.class
__NSArrayM
(lldb) po array.class
__NSArrayI
(lldb) po mutableArray.class
__NSArrayI
在这里可以看出,baseArray没有变(当然不会变🙄)依然是可变数组,array和mutableArray则是不可变数组
origin array: 0x608000047c80, 0x7fff52b7ebd8, (
aaaaa,
bbbb,
ccccc,
Block
)
copy array: 0x600000055f60, 0x7f80c141fe68, (
aaaaa,
bbbb,
ccccc,
Block
)
copy mutableArray: 0x60800004d6e0, 0x7f80c141fe70, (
aaaaa,
bbbb,
ccccc,
Block
)
这里可以看出array和mutableArray在copy方法时生成了新的对象
-[__NSArrayI removeObjectAtIndex:]: unrecognized selector sent to instance 0x60800004d6e0
最后mutableArray执行删除操作发生奔溃
*小结:用copy方法时,如果被copy对象为可变类型,此时为深拷贝,被赋值对象无论是否可变都将变为不可变对象
第三种:mutableCopy方法,NSArray赋值
NSArray *array = [[NSArray alloc]init];
NSMutableArray *mutableArray = [[NSMutableArray alloc]init];
NSArray *baseArray = [NSArray arrayWithObjects:@"aaaaa", @"bbbb", @"ccccc", @"Block", nil];
array = [baseArray mutableCopy];
mutableArray = [baseArray mutableCopy];
NSLog(@"origin array: %p, %p, %@",baseArray, &baseArray, baseArray);
NSLog(@"copy array: %p, %p, %@",array, &array, array);
NSLog(@"copy mutableArray: %p, %p, %@", mutableArray, &mutableArray, mutableArray);
[mutableArray removeObjectAtIndex:0];
我们继续运行,同样po一下:
(lldb) po baseArray.class
__NSArrayI
(lldb) po array.class
__NSArrayM
(lldb) po mutableArray.class
__NSArrayM
可以看到,array和mutableArray的class类型都是__NSArrayM,array不变数组在经过mutableCopy方法后变成了可变数组
origin array: 0x608000059cb0, 0x7fff5b530bd0, (
aaaaa,
bbbb,
ccccc,
Block
)
copy array: 0x60000005e090, 0x7fff5b530be0, (
aaaaa,
bbbb,
ccccc,
Block
)
copy mutableArray: 0x6000000576a0, 0x7fff5b530bd8, (
aaaaa,
bbbb,
ccccc,
Block
)
这里可以看出array和mutableArray在mutableCopy方法时生成了新的对象,[mutableArray removeObjectAtIndex:0];不会再引起奔溃。
*小结:用mutableCopy方法时,如果被mutableCopy对象为不可变类型,此时也为深拷贝,被赋值对象无论是否可变都将变为可变对象
第四种:mutableCopy方法,NSMutableArray赋值
NSArray *array = [[NSArray alloc]init];
NSMutableArray *mutableArray = [[NSMutableArray alloc]init];
NSMutableArray *baseArray = [NSMutableArray arrayWithObjects:@"aaaaa", @"bbbb", @"ccccc", @"Block", nil];
array = [baseArray mutableCopy];
mutableArray = [baseArray mutableCopy];
NSLog(@"origin array: %p, %p, %@",baseArray, &baseArray, baseArray);
NSLog(@"copy array: %p, %p, %@",array, &array, array);
NSLog(@"copy mutableArray: %p, %p, %@", mutableArray, &mutableArray, mutableArray);
[mutableArray removeObjectAtIndex:0];
我们继续运行,同样po一下:
(lldb) po baseArray.class
__NSArrayM
(lldb) po array.class
__NSArrayM
(lldb) po mutableArray.class
__NSArrayM
可以看到,三者class类型都是__NSArrayM,array不变数组在经过mutableCopy方法后变成了可变数组
origin array: 0x600000051490, 0x7fff54acdbd0, (
aaaaa,
bbbb,
ccccc,
Block
)
copy array: 0x600000056c80, 0x7fff54acdbe0, (
aaaaa,
bbbb,
ccccc,
Block
)
copy mutableArray: 0x60800005bf00, 0x7fff54acdbd8, (
aaaaa,
bbbb,
ccccc,
Block
)
这里可以看出array和mutableArray在mutableCopy方法时生成了新的对象,[mutableArray removeObjectAtIndex:0];不会再引起奔溃。
*小结:用mutableCopy方法时,如果被mutableCopy对象为可变类型,此时也为深拷贝,被赋值对象无论是否可变都将变为可变对象
总结:
1.copy在被拷贝对象为不可变类型时为浅拷贝,在被拷贝对象为可变类型时为深拷贝;
2.无论copy的被拷贝对象是否可变,其返回值一定为不可变类型;
3.mutableCopy为深拷贝,无论被拷贝对象是否可变,其返回值一定为可变类型;