Objective-C 之深拷贝和浅拷贝
Posted lisaloveyou1900
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Objective-C 之深拷贝和浅拷贝相关的知识,希望对你有一定的参考价值。
3月箴言
人的思想是了不起的,只要专注于某一项事业,就一定会做出使自己感到吃惊的成绩来。
1、iOS中关于深拷贝和浅拷贝的概念
浅拷贝:浅拷贝并不拷贝对象本身,只是对指向对象的指针进行拷贝
深拷贝:直接拷贝对象到内存中一块区域,然后把新对象的指针指向这块内存
在ios中并不是所有对象都支持Copy和MutableCopy,遵循NSCopying协议的类可以发送Copy协议,遵循NSMutableCopying协议的类可以发送MutableCopy消息。如果一个对象没有遵循这两个协议而发送Copy或者MutableCopy消息那么会发生异常。如果要遵循NSCopying协议,那么必须实现copyWithZone方法。如果要遵循NSMutableCopying协议那么必须实现mutableCopyWithZone方法。
2、可变对象和不可变对象调用深拷贝和浅拷贝方法的区别以及具体示例:
2.1非容器类不可变对象
- (void)immutableStrCopyAndMutCopy { NSString *immutableStr = @"不可变字符串"; NSMutableString *immutableStrCopy = [immutableStr copy]; NSMutableString *immutableStrMutCopy = [immutableStr mutableCopy]; // [immutableStrCopy appendString:@"22"]; [immutableStrMutCopy appendString:@"33"]; NSLog(@"immutableStrMutCopy = %@",immutableStrMutCopy); /* immutableStr_p = 0x107a58068 immutableStr = __NSCFConstantString immutableStrCopy_p = 0x107a58068 immutableStrCopy = __NSCFConstantString, immutableStrMutCopy_p = 0x6000034e07e0,immutableStrMutCopy= __NSCFString __NSCFConstantString 表示对象存储在常量区,__NSCFString表示对象存储在堆上 */ NSLog(@" immutableStr_p = %p immutableStr = %@ immutableStrCopy_p = %p immutableStrCopy = %@, immutableStrMutCopy_p = %p,immutableStrMutCopy= %@",immutableStr,[immutableStr class],immutableStrCopy,[immutableStrCopy class],immutableStrMutCopy,[immutableStrMutCopy class]); }
结论:
对非容器类的不可变对象 执行copy 是浅拷贝,地址相同,返回的也是不可变对象
执行mutableCopy 是深拷贝,地址不同,返回的是可变对象
2.2非容器类可变对象
- (void)mutableStrCopyAndMutCopy { NSMutableString *mutableStr = [NSMutableString stringWithFormat:@"可变字符串"]; NSMutableString *mutableStrCopy = [mutableStr copy]; //copy 之后 变为不可变对象,不可执行拼接操作,窒息该操作,直接崩溃!! // [mutableStrCopy appendString:@"copy 之后拼接"]; NSMutableString *mutableStrMutCopy = [mutableStr mutableCopy]; [mutableStrMutCopy appendString:@"mutcopy"]; /* mutableStr.p = 0x600001589230 mutableStr.class = __NSCFString mutableStr = 可变字符串 mutableStrCopy.p = 0x6000015890b0 mutableStrCopy.class = __NSCFString,mutableStrCopy = 可变字符串 mutableStrMutCopy.p = 0x6000015887b0,mutableStrMutCopy.class= __NSCFString,mutableStrMutCopy = 可变字符串mutcopy */ NSLog(@" mutableStr.p = %p mutableStr.class = %@ mutableStr = %@ mutableStrCopy.p = %p mutableStrCopy.class = %@,mutableStrCopy = %@ mutableStrMutCopy.p = %p,mutableStrMutCopy.class= %@,mutableStrMutCopy = %@",mutableStr,[mutableStr class],mutableStr,mutableStrCopy,[mutableStrCopy class],mutableStrCopy,mutableStrMutCopy,[mutableStrMutCopy class],mutableStrMutCopy); }
结论:
对于非容器类的可变对象 执行 copy 深拷贝,地址不同,返回的是不可变对象
执行mutableCopy,深拷贝,地址不同,返回的是可变对象
2.3容器类不可变对象
- (void)imArrayCopyAndMutCopy { NSString *immutableStr = @"不可变对象"; NSMutableString *mutableStr = [NSMutableString stringWithFormat:@"可变对象兮"]; NSArray *imArray = [NSArray arrayWithObjects:immutableStr,mutableStr, nil]; NSArray *imArrayCopy = [imArray copy]; NSArray *imArrayMutCopy = [imArray mutableCopy]; /* imArray.p = 0x60000259d960 imArray.class = __NSArrayI imArrayCopy.p = 0x60000259d960 imArrayCopy.class = __NSArrayI imArrayMutCopy.p = 0x600002b839f0,imArrayMutCopy.class= __NSArrayM 2019-03-03 12:13:35.401764+0800 MyNewTestDemo[13557:3186194] imArray ---tempStr.p = 0x1098d4088,tempStr = __NSCFConstantString,tempStr.class = 不可变对象 2019-03-03 12:13:35.401864+0800 MyNewTestDemo[13557:3186194] imArray ---tempStr.p = 0x600002b83b70,tempStr = __NSCFString,tempStr.class = 可变对象兮 2019-03-03 12:13:35.401945+0800 MyNewTestDemo[13557:3186194] imArrayCopy ---tempCopyStr.p = 0x1098d4088,tempCopyStr = __NSCFConstantString,tempCopyStr.class = 不可变对象 2019-03-03 12:13:35.402043+0800 MyNewTestDemo[13557:3186194] imArrayCopy ---tempCopyStr.p = 0x600002b83b70,tempCopyStr = __NSCFString,tempCopyStr.class = 可变对象兮 2019-03-03 12:13:35.402111+0800 MyNewTestDemo[13557:3186194] imArrayMutCopy ---tempMutCopyStr.p = 0x1098d4088,tempMutCopyStr = __NSCFConstantString,tempMutCopyStr.class = 不可变对象 2019-03-03 12:13:35.402171+0800 MyNewTestDemo[13557:3186194] imArrayMutCopy ---tempMutCopyStr.p = 0x600002b83b70,tempMutCopyStr = __NSCFString,tempMutCopyStr.class = 可变对象兮 */ NSLog(@" imArray.p = %p imArray.class = %@ imArrayCopy.p = %p imArrayCopy.class = %@ imArrayMutCopy.p = %p,imArrayMutCopy.class= %@",imArray,[imArray class],imArrayCopy,[imArrayCopy class],imArrayMutCopy,[imArrayMutCopy class]); for (id tempStr in imArray) { NSLog(@"imArray ---tempStr.p = %p,tempStr = %@,tempStr.class = %@ ",tempStr,[tempStr class],tempStr); } for (id tempCopyStr in imArrayCopy) { NSLog(@"imArrayCopy ---tempCopyStr.p = %p,tempCopyStr = %@,tempCopyStr.class = %@ ",tempCopyStr,[tempCopyStr class],tempCopyStr); } for (id tempMutCopyStr in imArrayMutCopy) { NSLog(@"imArrayMutCopy ---tempMutCopyStr.p = %p,tempMutCopyStr = %@,tempMutCopyStr.class = %@ ",tempMutCopyStr,[tempMutCopyStr class],tempMutCopyStr); } }
结论:对于容器类的不可变对象 执行copy 对于容器来说是浅copy,地址相同,且返回的是不可变对象
执行mutableCopy 对于容器来说是深拷贝,地址不同,且返回的是可变对象。
对于容器内的对象(可变或不可变对象)而言,无论容器执行的是copy还是mutableCopy,这些对象执行的都是浅拷贝
2.4容器类可变对象
- (void)mutArrayCopyAndMutCopy { NSString *immutableStr = @"不可变对象"; NSMutableString *mutableStr = [NSMutableString stringWithFormat:@"可变对象兮"]; NSMutableArray *mutArray = [NSMutableArray arrayWithObjects:immutableStr,mutableStr, nil]; /* mutArray.p = 0x600002c17000 mutArray.class = __NSArrayM mutArray.copy.p = 0x60000221ace0 mutArray.copy.Class = __NSArrayI mutArray.mutCopy.p = 0x600002c16fd0,mutArray.mutCopy.p= __NSArrayM 2019-03-03 12:24:00.751299+0800 MyNewTestDemo[13742:3202669] mutArray ---tempStr.p = 0x10ec73088,tempStr = __NSCFConstantString,tempStr.class = 不可变对象 2019-03-03 12:24:00.751410+0800 MyNewTestDemo[13742:3202669] mutArray ---tempStr.p = 0x600002c17330,tempStr = __NSCFString,tempStr.class = 可变对象兮 2019-03-03 12:24:00.751502+0800 MyNewTestDemo[13742:3202669] mutArray.copy ---tempCopyStr.p = 0x10ec73088,tempCopyStr = __NSCFConstantString,tempCopyStr.class = 不可变对象 2019-03-03 12:24:00.751594+0800 MyNewTestDemo[13742:3202669] mutArray.copy ---tempCopyStr.p = 0x600002c17330,tempCopyStr = __NSCFString,tempCopyStr.class = 可变对象兮 2019-03-03 12:24:00.751694+0800 MyNewTestDemo[13742:3202669] mutArray.mutCopy ---tempMutCopyStr.p = 0x10ec73088,tempMutCopyStr = __NSCFConstantString,tempMutCopyStr.class = 不可变对象 2019-03-03 12:24:00.751789+0800 MyNewTestDemo[13742:3202669] mutArray.mutCopy ---tempMutCopyStr.p = 0x600002c17330,tempMutCopyStr = __NSCFString,tempMutCopyStr.class = 可变对象兮 */ NSLog(@" mutArray.p = %p mutArray.class = %@ mutArray.copy.p = %p mutArray.copy.Class = %@ mutArray.mutCopy.p = %p,mutArray.mutCopy.p= %@",mutArray,[mutArray class],[mutArray copy],[[mutArray copy] class],[mutArray mutableCopy],[[mutArray mutableCopy] class]); for (id tempStr in mutArray) { NSLog(@"mutArray ---tempStr.p = %p,tempStr = %@,tempStr.class = %@ ",tempStr,[tempStr class],tempStr); } for (id tempCopyStr in [mutArray copy]) { NSLog(@"mutArray.copy ---tempCopyStr.p = %p,tempCopyStr = %@,tempCopyStr.class = %@ ",tempCopyStr,[tempCopyStr class],tempCopyStr); } for (id tempMutCopyStr in [mutArray mutableCopy]) { NSLog(@"mutArray.mutCopy ---tempMutCopyStr.p = %p,tempMutCopyStr = %@,tempMutCopyStr.class = %@ ",tempMutCopyStr,[tempMutCopyStr class],tempMutCopyStr); } }
结论:对于容器类可变对象 执行copy,深拷贝,地址不同,返回的是不可变对象
执行mutableCopy,深拷贝,地址不同,返回的是不可变对象
容器内的对象(无论可变或不可变),均为浅拷贝(地址相同)
- (void)imDicCopyAndMutCopy { NSString *immutableStrOne = @"不可变对象1"; NSMutableString *mutableStrOne = [NSMutableString stringWithFormat:@"可变对象1"]; NSString *immutableStrTwo = @"不可变对象2"; NSMutableString *mutableStrTwo = [NSMutableString stringWithFormat:@"可变对象2"]; /* immutableDic.p = 0x6000003d2400 immutableDic.class = __NSDictionaryI immutableDic.copy.p = 0x6000003d2400 immutableDic.copy.class = __NSDictionaryI immutableDic.mutcopy.p = 0x600002dc8e00,immutableDic.mutcopy.class= __NSDictionaryM 2019-03-03 12:37:08.098513+0800 MyNewTestDemo[13840:3214742] immutableDic ---key.p = 0x600002398e40,key.class = __NSCFString,key = 可变对象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可变对象1 2019-03-03 12:37:08.098588+0800 MyNewTestDemo[13840:3214742] immutableDic ---key.p = 0x600002399260,key.class = __NSCFString,key = 可变对象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可变对象1 2019-03-03 12:37:08.098698+0800 MyNewTestDemo[13840:3214742] immutableDic ---key.p = 0x105a20148,key.class = __NSCFConstantString,key = 不可变对象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可变对象1 2019-03-03 12:37:08.098785+0800 MyNewTestDemo[13840:3214742] immutableDic ---key.p = 0x105a20188,key.class = __NSCFConstantString,key = 不可变对象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可变对象1 2019-03-03 12:37:08.098873+0800 MyNewTestDemo[13840:3214742] immutableDic.copy ---key.p = 0x600002398e40,key.class = __NSCFString,key = 可变对象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可变对象1 2019-03-03 12:37:08.098950+0800 MyNewTestDemo[13840:3214742] immutableDic.copy ---key.p = 0x600002399260,key.class = __NSCFString,key = 可变对象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可变对象1 2019-03-03 12:37:08.099037+0800 MyNewTestDemo[13840:3214742] immutableDic.copy ---key.p = 0x105a20148,key.class = __NSCFConstantString,key = 不可变对象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可变对象1 2019-03-03 12:37:08.099140+0800 MyNewTestDemo[13840:3214742] immutableDic.copy ---key.p = 0x105a20188,key.class = __NSCFConstantString,key = 不可变对象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可变对象1 2019-03-03 12:37:08.160496+0800 MyNewTestDemo[13840:3214742] immutableDic.mutcopy ---key.p = 0x105a20188,key.class = __NSCFConstantString,key = 不可变对象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可变对象1 2019-03-03 12:37:08.160610+0800 MyNewTestDemo[13840:3214742] immutableDic.mutcopy ---key.p = 0x600002399260,key.class = __NSCFString,key = 可变对象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可变对象1 2019-03-03 12:37:08.160716+0800 MyNewTestDemo[13840:3214742] immutableDic.mutcopy ---key.p = 0x105a20148,key.class = __NSCFConstantString,key = 不可变对象1 ,obj.p = 0x105a20148,obj.class = __NSCFConstantString,obj = 不可变对象1 2019-03-03 12:37:08.160811+0800 MyNewTestDemo[13840:3214742] immutableDic.mutcopy ---key.p = 0x600002398e40,key.class = __NSCFString,key = 可变对象2 ,obj.p = 0x600002398de0,obj.class = __NSCFString,obj = 可变对象1 */ NSDictionary *immutableDic = @{immutableStrOne:immutableStrOne,immutableStrTwo:mutableStrOne,mutableStrOne:immutableStrOne,mutableStrTwo:mutableStrOne}; NSLog(@" immutableDic.p = %p immutableDic.class = %@ immutableDic.copy.p = %p immutableDic.copy.class = %@ immutableDic.mutcopy.p = %p,immutableDic.mutcopy.class= %@",immutableDic,[immutableDic class],[immutableDic copy],[[immutableDic copy] class],[immutableDic mutableCopy],[[immutableDic mutableCopy] class]); [immutableDic enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) { NSLog(@"immutableDic ---key.p = %p,key.class = %@,key = %@ ,obj.p = %p,obj.class = %@,obj = %@ ",key,[key class],key,obj,[obj class],obj); }]; [[immutableDic copy] enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) { NSLog(@"immutableDic.copy ---key.p = %p,key.class = %@,key = %@ ,obj.p = %p,obj.class = %@,obj = %@ ",key,[key class],key,obj,[obj class],obj); }]; [[immutableDic mutableCopy] enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) { NSLog(@"immutableDic.mutcopy ---key.p = %p,key.class = %@,key = %@ ,obj.p = %p,obj.class = %@,obj = %@ ",key,[key class],key,obj,[obj class],obj); }]; }
结论:容器类不可变对象 字典和数组的结论是一致的,且对于字典中的key或value ,都是浅拷贝
可以简单整理为:不可变对象的copy,都是浅拷贝,地址相同,
可变对象的copy和mutablecopy,都是深拷贝,
copy方法返回的是不可变对象,mutableCopy返回的是可变对象,
容器对象内的对象始终是浅拷贝。
代码可点击github,项目内搜索关键字copy and mutableCopy
以上是关于Objective-C 之深拷贝和浅拷贝的主要内容,如果未能解决你的问题,请参考以下文章