美文网首页
深浅拷贝

深浅拷贝

作者: QYCD | 来源:发表于2021-03-23 17:49 被阅读0次

野指针: 指向不可用内存区域的指针
不是NULL指针,是指向"垃圾"内存的指针

原因:

  1. 指针变量没有被初始化
  2. 指针指向的内存被回收,但指针未释放

NSString:

    NSString *earth = @"Earth";
    NSString *earthCopy = [earth copy];
    NSString *earthMCopy = [earth mutableCopy];
    
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", earth, &earth, [earth class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", earthCopy, &earthCopy, [earthCopy class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", earthMCopy, &earthMCopy, [earthMCopy class]);
    
    /**
     [ViewController.m:33行] 内存地址: 0x1004840a8; 指针地址: 0x16f983db0; class: __NSCFConstantString
     [ViewController.m:34行] 内存地址: 0x1004840a8; 指针地址: 0x16f983da8; class: __NSCFConstantString
     [ViewController.m:35行] 内存地址: 0x282d34270; 指针地址: 0x16f983da0; class: __NSCFString
     */
    /**
     copy时 内存地址与原地址一样,指针地址改变,NSString类型 -> 拷贝了指针,指向与原对象同样的内存地址
     
     mutableCopy时 内存地址、指针地址均发生改变, NSMutableString类型 -> 内容拷贝 内存地址与指针地址均改变
     */

NSMutableString:

    NSMutableString *china = [NSMutableString stringWithString:@"China"];
    NSString *chinaCopy = [china copy];
    NSString *chinaMCopy = [china mutableCopy];
    
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", china, &china, [china class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", chinaCopy, &chinaCopy, [chinaCopy class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", chinaMCopy, &chinaMCopy, [chinaMCopy class]);
    
    /**
     [ViewController.m:43行] 内存地址: 0x282d34660; 指针地址: 0x16f983d98; class: __NSCFString
     [ViewController.m:44行] 内存地址: 0x9680a85efaff77c0; 指针地址: 0x16f983d90; class: NSTaggedPointerString
     [ViewController.m:45行] 内存地址: 0x282d341e0; 指针地址: 0x16f983d88; class: __NSCFString
     */
    /**
     copy时 内存地址、指针地址均发生改变  NSString类型 -> 内容拷贝 内存地址与指针地址均发生改变
     
     mutableCopy时 内存地址、指针地址均发生改变 NSMutableString类型 -> 内容拷贝
     */

NSDictionary:

    NSDictionary *beijingDic = @{@"area": @"朝阳"};
    NSDictionary *beijingDicCopy = [beijingDic copy];
    NSDictionary *beijingDicMCopy = [beijingDic mutableCopy];
    
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", beijingDic, &beijingDic, [beijingDic class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", beijingDicCopy, &beijingDicCopy, [beijingDicCopy class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", beijingDicMCopy, &beijingDicMCopy, [beijingDicMCopy class]);
    
    /**
     [ViewController.m:53行] 内存地址: 0x282364200; 指针地址: 0x16f983d80; class: __NSSingleEntryDictionaryI
     [ViewController.m:54行] 内存地址: 0x282364200; 指针地址: 0x16f983d78; class: __NSSingleEntryDictionaryI
     [ViewController.m:55行] 内存地址: 0x282364240; 指针地址: 0x16f983d70; class: __NSDictionaryM
     */
    /**
     copy 内存地址不变,指针地址改变 不可变类型 -> 指针拷贝
     
     mutableCopy 内存地址、指针地址改变 可变类型 -> 内容拷贝
     */

NSMutableDictionary:

    NSMutableDictionary *shanghaiMutableDic = [NSMutableDictionary dictionary];
    shanghaiMutableDic[@"air"] = @"hongqiao";
    
    NSDictionary *shanghaiMutableDicCopy = [shanghaiMutableDic copy];
    NSDictionary *shanghaiMutableDicMCopy = [shanghaiMutableDic mutableCopy];
    
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", shanghaiMutableDic, &shanghaiMutableDic, [shanghaiMutableDic class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", shanghaiMutableDicCopy, &shanghaiMutableDicCopy, [shanghaiMutableDicCopy class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", shanghaiMutableDicMCopy, &shanghaiMutableDicMCopy, [shanghaiMutableDicMCopy class]);
    /**
     [ViewController.m:65行] 内存地址: 0x282364380; 指针地址: 0x16f983d68; class: __NSDictionaryM
     [ViewController.m:66行] 内存地址: 0x2823643a0; 指针地址: 0x16f983d60; class: __NSFrozenDictionaryM
     [ViewController.m:67行] 内存地址: 0x282364360; 指针地址: 0x16f983d58; class: __NSDictionaryM
     */
    /**
     copy 内存地址、指针地址发生改变 不可变类型 -> 内容拷贝
     
     mutableCopy 内存地址、指针地址发生改变 可变类型 -> 内容拷贝
     */

NSArray:

    NSArray *provinceArr = @[@"beijing", @"shanghai"];
    NSArray *provinceArrCopy = [provinceArr copy];
    NSArray *provinceArrMCopy = [provinceArr mutableCopy];
    
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", provinceArr, &provinceArr, [provinceArr class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", provinceArrCopy, &provinceArrCopy, [provinceArrCopy class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", provinceArrMCopy, &provinceArrMCopy, [provinceArrMCopy class]);
    /**
     [ViewController.m:75行] 内存地址: 0x282364340; 指针地址: 0x16f983d50; class: __NSArrayI
     [ViewController.m:76行] 内存地址: 0x282364340; 指针地址: 0x16f983d48; class: __NSArrayI
     [ViewController.m:77行] 内存地址: 0x282d2a010; 指针地址: 0x16f983d40; class: __NSArrayM
     */
    /**
     copy 内存地址不变,指针地址改变 不可变类型 -> 指针拷贝
     
     mutableCopy 内存地址、指针地址均改变 可变类型 -> 内容拷贝
     */

NSMutableArray:

    NSMutableArray *cityArr = [NSMutableArray arrayWithObjects:@"tianjin", @"chongqing", nil];
    NSArray *cityArrCopy = [cityArr copy];
    NSArray *cityArrMCopy = [cityArr mutableCopy];
    
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", cityArr, &cityArr, [cityArr class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", cityArrCopy, &cityArrCopy, [cityArrCopy class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", cityArrMCopy, &cityArrMCopy, [cityArrMCopy class]);
    /**
     [ViewController.m:85行] 内存地址: 0x282d29830; 指针地址: 0x16f983d38; class: __NSArrayM
     [ViewController.m:86行] 内存地址: 0x2823651c0; 指针地址: 0x16f983d30; class: __NSArrayI
     [ViewController.m:87行] 内存地址: 0x282d2a2e0; 指针地址: 0x16f983d28; class: __NSArrayM
     */
    /**
     copy 内存地址、指针地址均改变 不可变类型 -> 内容拷贝
     
     mutableCopy 内存地址、指针地址均改变 可变类型 -> 内容拷贝
     */

总结:

类型 拷贝方法 副本对象 是否产生新对象 拷贝类型
NSString copy NSString 浅拷贝(指针拷贝)
mutableCopy NSMutableString 深拷贝(内容拷贝)
NSMutableString copy NSString 深拷贝(内容拷贝)
mutableCopy NSMutableString 深拷贝(内容拷贝)
NSDictionary copy NSDictionary 浅拷贝(指针拷贝)
mutableCopy NSMutableDictionary 深拷贝(单层或完全)
NSMutableDictionary copy NSDictionary 深拷贝(单层或完全)
mutableCopy NSMutableDictionary 深拷贝(单层或完全)
NSArray copy NSArray 浅拷贝(指针拷贝)
mutableCopy NSMutableArray 深拷贝(单层或完全)
NSMutableArray copy NSArray 深拷贝(单层或完全)
mutableCopy NSMutableArray 深拷贝(单层或完全)

浅拷贝:
浅拷贝并不拷贝对象本身,仅仅是拷贝指向对象的指针;
深拷贝:
深拷贝是直接拷贝整个对象内容到另一块内存中
即: 浅拷贝是指针的拷贝,深拷贝是内容拷贝

  • 不可变对象
    • 进行copy都是浅拷贝
    • 进行mutableCopy都是深拷贝
  • 可变对象
    • 进行copy或mutableCopy都是深拷贝
  • 不论可变还是不可变对象,进行copy产生的都是不可变对象,mutableCopy产生的都是可变对象

    NSArray *arr = @[@"a", @"b", @"c"];
    NSArray *arrCopy = [arr copy];
    NSMutableArray *arrMCopy = [arr mutableCopy];
    
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", arr, &arr, [arr class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", arrCopy, &arrCopy, [arrCopy class]);
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", arrMCopy, &arrMCopy, [arrMCopy class]);
    /**
     [ViewController.m:41行] 内存地址: 0x28029c270; 指针地址: 0x16ddc7398; class: __NSArrayI
     [ViewController.m:42行] 内存地址: 0x28029c270; 指针地址: 0x16ddc7390; class: __NSArrayI
     [ViewController.m:43行] 内存地址: 0x28029c360; 指针地址: 0x16ddc7388; class: __NSArrayM
     */

    for (NSString *item in arr) {
        NSLog(@"元素: %@; 内存地址: %p; 指针地址: %p; class: %@", item, item, &item, [item class]);
    }
    NSLog(@"******************************************************************************");
    for (NSString *item in arrCopy) {
        NSLog(@"元素: %@; 内存地址: %p; 指针地址: %p; class: %@", item, item, &item, [item class]);
    }
    NSLog(@"******************************************************************************");
    for (NSString *item in arrMCopy) {
        NSLog(@"元素: %@; 内存地址: %p; 指针地址: %p; class: %@", item, item, &item, [item class]);
    }
    /**
     [ViewController.m:48行] 元素: a; 内存地址: 0x1020400b0; 指针地址: 0x16ddc7380; class: __NSCFConstantString
     [ViewController.m:48行] 元素: b; 内存地址: 0x1020400d0; 指针地址: 0x16ddc7380; class: __NSCFConstantString
     [ViewController.m:48行] 元素: c; 内存地址: 0x1020400f0; 指针地址: 0x16ddc7380; class: __NSCFConstantString
     [ViewController.m:50行] ******************************************************************************
     [ViewController.m:52行] 元素: a; 内存地址: 0x1020400b0; 指针地址: 0x16ddc7338; class: __NSCFConstantString
     [ViewController.m:52行] 元素: b; 内存地址: 0x1020400d0; 指针地址: 0x16ddc7338; class: __NSCFConstantString
     [ViewController.m:52行] 元素: c; 内存地址: 0x1020400f0; 指针地址: 0x16ddc7338; class: __NSCFConstantString
     [ViewController.m:54行] ******************************************************************************
     [ViewController.m:56行] 元素: a; 内存地址: 0x1020400b0; 指针地址: 0x16ddc72f0; class: __NSCFConstantString
     [ViewController.m:56行] 元素: b; 内存地址: 0x1020400d0; 指针地址: 0x16ddc72f0; class: __NSCFConstantString
     [ViewController.m:56行] 元素: c; 内存地址: 0x1020400f0; 指针地址: 0x16ddc72f0; class: __NSCFConstantString
     */

可以看到对NSArray进行深拷贝(mutableCopy)时,新生了指向另一块内存的容器对象,但打印其内部元素地址,发现元素内存地址未改变,仍指向原内存地址

单层深拷贝:
容器类对象,进行深拷贝时,虽然外层的内存地址发生了改变(生成了新的指向另一块内存的容器对象),但是里面内容元素的内存地址并未发生改变,仅仅进行了浅拷贝

对其进行完全深拷贝:

    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr];
    NSArray *objectArr = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    NSLog(@"内存地址: %p; 指针地址: %p; class: %@", objectArr, &objectArr, [objectArr class]);
    for (NSString *item in objectArr) {
        NSLog(@"元素: %@; 内存地址: %p; 指针地址: %p; class: %@", item, item, &item, [item class]);
    }
    /**
     [ViewController.m:89行] 内存地址: 0x282bae2b0; 指针地址: 0x16bac73a0; class: __NSArrayI
     [ViewController.m:91行] 元素: a; 内存地址: 0x899fa662d40629ce; 指针地址: 0x16bac7398; class: NSTaggedPointerString
     [ViewController.m:91行] 元素: b; 内存地址: 0x899fa662d406284e; 指针地址: 0x16bac7398; class: NSTaggedPointerString
     [ViewController.m:91行] 元素: c; 内存地址: 0x899fa662d40628ce; 指针地址: 0x16bac7398; class: NSTaggedPointerString
     */

PS: unarchiveObjectWithData方法返回id类型,对于容器类,返回的是其不可变类型

自定义类型对象:

    NSMutableArray *personList = [NSMutableArray array];
    for (int i = 0; i < 3; i++) {
        Person *person = [[Person alloc] init];
        person.age = i + 18;
        person.name = [NSString stringWithFormat:@"小明%d号", i + 1];
        [personList addObject:person];
    }
    
    NSArray *personListCopy = [personList copy];
    NSMutableArray *personListMCopy = [personList mutableCopy];
    
    NSLog(@"内存地址: %p; class: %@", personList, [personList class]);
    NSLog(@"内存地址: %p; class: %@", [personListCopy copy], [personListCopy class]);
    NSLog(@"内存地址: %p; class: %@", [personListMCopy mutableCopy], [personListMCopy class]);
    NSLog(@"******************************************************************************");
    
    for (Person *item in personList) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    NSLog(@"******************************************************************************");
    for (Person *item in personListCopy) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    NSLog(@"******************************************************************************");
    for (Person *item in personListMCopy) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    /**
     [ViewController.m:41行] 内存地址: 0x28132edf0; class: __NSArrayM
     [ViewController.m:42行] 内存地址: 0x28132edc0; class: __NSArrayI
     [ViewController.m:43行] 内存地址: 0x28132ed30; class: __NSArrayM
     [ViewController.m:44行] ******************************************************************************
     [ViewController.m:47行] name: 小明1号; name: 0x281d75360; age: 0x12; 内存地址: 0x281d75380; class: Person
     [ViewController.m:47行] name: 小明2号; name: 0x281d74880; age: 0x13; 内存地址: 0x281d74580; class: Person
     [ViewController.m:47行] name: 小明3号; name: 0x281d749c0; age: 0x14; 内存地址: 0x281d748a0; class: Person
     [ViewController.m:49行] ******************************************************************************
     [ViewController.m:51行] name: 小明1号; name: 0x281d75360; age: 0x12; 内存地址: 0x281d75380; class: Person
     [ViewController.m:51行] name: 小明2号; name: 0x281d74880; age: 0x13; 内存地址: 0x281d74580; class: Person
     [ViewController.m:51行] name: 小明3号; name: 0x281d749c0; age: 0x14; 内存地址: 0x281d748a0; class: Person
     [ViewController.m:53行] ******************************************************************************
     [ViewController.m:55行] name: 小明1号; name: 0x281d75360; age: 0x12; 内存地址: 0x281d75380; class: Person
     [ViewController.m:55行] name: 小明2号; name: 0x281d74880; age: 0x13; 内存地址: 0x281d74580; class: Person
     [ViewController.m:55行] name: 小明3号; name: 0x281d749c0; age: 0x14; 内存地址: 0x281d748a0; class: Person
     */

从打印结果看: 数组内存地址均改变,进行了深拷贝,但其内部元素内存地址未发生改变,即单层深拷贝

如果改变某个数组内元素的值,其他数组内元组的值也会发生改变:

    for (Person *item in personListCopy) {
        item.name = @"小红";
    }
    NSLog(@"******************************************************************************");
    for (Person *item in personList) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    NSLog(@"******************************************************************************");
    for (Person *item in personListCopy) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    NSLog(@"******************************************************************************");
    for (Person *item in personListMCopy) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    /**
     [ViewController.m:71行] name: 小红; name: 0x102b10130; age: 0x12; 内存地址: 0x281d75380; class: Person
     [ViewController.m:71行] name: 小红; name: 0x102b10130; age: 0x13; 内存地址: 0x281d74580; class: Person
     [ViewController.m:71行] name: 小红; name: 0x102b10130; age: 0x14; 内存地址: 0x281d748a0; class: Person
     [ViewController.m:73行] ******************************************************************************
     [ViewController.m:75行] name: 小红; name: 0x102b10130; age: 0x12; 内存地址: 0x281d75380; class: Person
     [ViewController.m:75行] name: 小红; name: 0x102b10130; age: 0x13; 内存地址: 0x281d74580; class: Person
     [ViewController.m:75行] name: 小红; name: 0x102b10130; age: 0x14; 内存地址: 0x281d748a0; class: Person
     [ViewController.m:77行] ******************************************************************************
     [ViewController.m:79行] name: 小红; name: 0x102b10130; age: 0x12; 内存地址: 0x281d75380; class: Person
     [ViewController.m:79行] name: 小红; name: 0x102b10130; age: 0x13; 内存地址: 0x281d74580; class: Person
     [ViewController.m:79行] name: 小红; name: 0x102b10130; age: 0x14; 内存地址: 0x281d748a0; class: Person
     */

改变了personListCopy中Person对象的name值,其原数组personList和personListMCopy中对应元素均发生改变 -> 对应的Person对象内存地址未发生改变,所以改变其中任何一个Person对象的值 其他也会受到影响


完全深拷贝:
方式一:

先来看一个NSArray的实例方法:

- (instancetype)initWithArray:(NSArray<ObjectType> *)array 
                    copyItems:(BOOL)flag;

查看其文档解释:

flag:
If YES, each object in array receives a copyWithZone: message to create a copy of the object—objects must conform to the NSCopying protocol. In a managed memory environment, this is instead of the retain message the object would otherwise receive. The object copy is then added to the returned array.
If NO, then in a managed memory environment each object in array simply receives a retain message when it is added to the returned array.
The copyWithZone: method performs a shallow copy. If you have a collection of arbitrary depth, passing YES for the flag parameter will perform an immutable copy of the first level below the surface. If you pass NO the mutability of the first level is unaffected. In either case, the mutability of all deeper levels is unaffected.

大意就是如果flag给YES,则会对NSArray内元素深拷贝一次
此外,我们知道不是所有的类都支持拷贝,只有遵循NSCopying协议的类,才支持copy拷贝,遵循NSMutableCopying协议的类,才支持mutableCopy拷贝;如果没有遵循相应协议的类,运用拷贝会发生异常
自定义的类,遵循NSCopying、NSMutableCopy协议,重写- (id)copyWithZone:(NSZone *)zone和- (id)mutableCopyWithZone:(NSZone *)zone这两个方法
比如: 我自定义的Person类,直接进行copy会发生异常:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person copyWithZone:]: unrecognized selector sent to instance 0x2802809e0'

利用YYModel库:

#import "Person.h"
#import <YYModel/YYModel.h>

@implementation Person

- (id)copyWithZone:(NSZone *)zone {return [self yy_modelCopy];}

@end
    NSMutableArray *personList = [NSMutableArray array];
    for (int i = 0; i < 3; i++) {
        Person *person = [[Person alloc] init];
        person.age = i + 18;
        person.name = [NSString stringWithFormat:@"小明%d号", i + 1];
        [personList addObject:person];
    }
    
    NSArray *personListCopy = [personList copy];
    NSMutableArray *personListMCopy = [personList mutableCopy];
    
    NSArray *personArr = [[NSArray alloc] initWithArray:personList copyItems:YES];
    NSLog(@"内存地址: %p; class: %@", personArr, [personArr class]);
    for (Person *item in personArr) {
        item.name = @"小红";
    }
    for (Person *item in personArr) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }

    for (Person *item in personList) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    for (Person *item in personListCopy) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    for (Person *item in personListMCopy) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    /**
     [ViewController.m:42行] 内存地址: 0x2834dba20; class: __NSArrayI
     [ViewController.m:47行] name: 小红; name: 0x1006580f0; age: 0x12; 内存地址: 0x283aef580; class: Person
     [ViewController.m:47行] name: 小红; name: 0x1006580f0; age: 0x13; 内存地址: 0x283aef780; class: Person
     [ViewController.m:47行] name: 小红; name: 0x1006580f0; age: 0x14; 内存地址: 0x283aef7a0; class: Person
     [ViewController.m:51行] name: 小明1号; name: 0x283a90fa0; age: 0x12; 内存地址: 0x283a913a0; class: Person
     [ViewController.m:51行] name: 小明2号; name: 0x283a90580; age: 0x13; 内存地址: 0x283a905a0; class: Person
     [ViewController.m:51行] name: 小明3号; name: 0x283a90480; age: 0x14; 内存地址: 0x283a90680; class: Person
     [ViewController.m:54行] name: 小明1号; name: 0x283a90fa0; age: 0x12; 内存地址: 0x283a913a0; class: Person
     [ViewController.m:54行] name: 小明2号; name: 0x283a90580; age: 0x13; 内存地址: 0x283a905a0; class: Person
     [ViewController.m:54行] name: 小明3号; name: 0x283a90480; age: 0x14; 内存地址: 0x283a90680; class: Person
     [ViewController.m:57行] name: 小明1号; name: 0x283a90fa0; age: 0x12; 内存地址: 0x283a913a0; class: Person
     [ViewController.m:57行] name: 小明2号; name: 0x283a90580; age: 0x13; 内存地址: 0x283a905a0; class: Person
     [ViewController.m:57行] name: 小明3号; name: 0x283a90480; age: 0x14; 内存地址: 0x283a90680; class: Person
     */

可以看到,经过NSArray *personArr = [[NSArray alloc] initWithArray:personList copyItems:YES]; personArr中Person对象的内存地址也发生了改变,即使修改了Person实例中name元素的值,也不影响原list中元素的值。

方式二:

利用解归档

    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:personList];
    NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data];

使用解归档时,自定义类需要遵循<NSCoding>,否则会发生异常

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person encodeWithCoder:]: unrecognized selector sent to instance 0x2839e8fe0'

这里依然使用YYModel库的方式:

#import "Person.h"
#import <YYModel/YYModel.h>

@implementation Person

- (void)encodeWithCoder:(NSCoder *)aCoder { [self yy_modelEncodeWithCoder:aCoder]; }
- (id)initWithCoder:(NSCoder *)aDecoder { self = [super init]; return [self yy_modelInitWithCoder:aDecoder]; }

@end
    NSMutableArray *personList = [NSMutableArray array];
    for (int i = 0; i < 3; i++) {
        Person *person = [[Person alloc] init];
        person.age = i + 18;
        person.name = [NSString stringWithFormat:@"小明%d号", i + 1];
        [personList addObject:person];
    }
    NSArray *personListCopy = [personList copy];
    NSMutableArray *personListMCopy = [personList mutableCopy];
    NSLog(@"内存地址: %p; class: %@", personList, [personList class]);
    for (Person *item in personList) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    NSLog(@"内存地址: %p; class: %@", personListCopy, [personListCopy class]);
    for (Person *item in personListCopy) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    NSLog(@"内存地址: %p; class: %@", personListMCopy, [personListMCopy class]);
    for (Person *item in personListMCopy) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    NSLog(@"******************************************************************************");
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:personList];
    NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    NSLog(@"内存地址: %p; class: %@", arr, [arr class]);
    for (Person *item in arr) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    NSLog(@"******************************************************************************");
    for (Person *item in arr) {
        item.name = @"哈哈";
    }
    NSLog(@"内存地址: %p; class: %@", personListMCopy, [personListMCopy class]);
    for (Person *item in personList) {
        NSLog(@"name: %@; name: %p; age: %p; 内存地址: %p; class: %@", item.name, item.name, item.age, item, [item class]);
    }
    /**
     [ViewController.m:39行] 内存地址: 0x281a40960; class: __NSArrayM
     [ViewController.m:41行] name: 小明1号; name: 0x2814130a0; age: 0x12; 内存地址: 0x281411fa0; class: Person
     [ViewController.m:41行] name: 小明2号; name: 0x281411920; age: 0x13; 内存地址: 0x281413060; class: Person
     [ViewController.m:41行] name: 小明3号; name: 0x281411a60; age: 0x14; 内存地址: 0x281411940; class: Person
     [ViewController.m:43行] 内存地址: 0x281a40990; class: __NSArrayI
     [ViewController.m:45行] name: 小明1号; name: 0x2814130a0; age: 0x12; 内存地址: 0x281411fa0; class: Person
     [ViewController.m:45行] name: 小明2号; name: 0x281411920; age: 0x13; 内存地址: 0x281413060; class: Person
     [ViewController.m:45行] name: 小明3号; name: 0x281411a60; age: 0x14; 内存地址: 0x281411940; class: Person
     [ViewController.m:47行] 内存地址: 0x281a40b40; class: __NSArrayM
     [ViewController.m:49行] name: 小明1号; name: 0x2814130a0; age: 0x12; 内存地址: 0x281411fa0; class: Person
     [ViewController.m:49行] name: 小明2号; name: 0x281411920; age: 0x13; 内存地址: 0x281413060; class: Person
     [ViewController.m:49行] name: 小明3号; name: 0x281411a60; age: 0x14; 内存地址: 0x281411940; class: Person
     [ViewController.m:51行] ******************************************************************************
     [ViewController.m:54行] 内存地址: 0x281a5c390; class: __NSArrayM
     [ViewController.m:56行] name: 小明1号; name: 0x281467500; age: 0x12; 内存地址: 0x2814675e0; class: Person
     [ViewController.m:56行] name: 小明2号; name: 0x281467640; age: 0x13; 内存地址: 0x281467680; class: Person
     [ViewController.m:56行] name: 小明3号; name: 0x281467540; age: 0x14; 内存地址: 0x281467560; class: Person
     [ViewController.m:58行] ******************************************************************************
     [ViewController.m:62行] 内存地址: 0x281a40b40; class: __NSArrayM
     [ViewController.m:64行] name: 小明1号; name: 0x2814130a0; age: 0x12; 内存地址: 0x281411fa0; class: Person
     [ViewController.m:64行] name: 小明2号; name: 0x281411920; age: 0x13; 内存地址: 0x281413060; class: Person
     [ViewController.m:64行] name: 小明3号; name: 0x281411a60; age: 0x14; 内存地址: 0x281411940; class: Person
     */

根据打印的Person类内存地址,经过解归档后,实现了完全深拷贝

对于深浅拷贝的描述,有人这么形容: 浅拷贝就像你的影子,你挂了,影子也没了;深拷贝好比克隆人,你挂了,它还在

参考:
iOS进阶之深拷贝和浅拷贝
iOS对象复制(copy与mutableCopy)

相关文章

  • 2018-08-29

    深浅拷贝 1.根据拷贝内容的不同,分为深浅拷贝 深拷贝:内容...

  • js的深浅拷贝

    js的深浅拷贝可以分为数组的深浅拷贝和对象的深浅拷贝 一、数组的深浅拷贝如果只是简单的将数组中的元素付给另外一个数...

  • Python—浅拷贝与深拷贝

    浅拷贝 深拷贝 深浅拷贝的作用

  • 深浅拷贝

    先来了解一下这些:在js中变量类型基本分为两种:基本数据类型和引用数据类型;基本类型:Underfied Null...

  • 深浅拷贝

    浅拷贝是对一个对象的顶层拷贝。通俗的理解就是:拷贝了引用,并没有拷贝内容。 深拷贝是对于一个对象所有层次的拷贝(递...

  • 深浅拷贝

    深浅拷贝.copy 浅拷贝 这是一个方法,浅拷贝修改可变类型是会将原数据也一块修改 Copy.deepcopy 深...

  • 深浅拷贝

    1:is 和 ==的区别 is 是比较两个引用是否指向了同一个对象(地址引用比较)。== 是比较两个对象是否相等。...

  • 深浅拷贝

    函数的传递,与matlab不同,具有以下特点: 1.直接赋值会带来不同ID,例如,a=2,b=2 2.传递引用赋值...

  • 深浅拷贝

    最近一直被问到深浅拷贝的问题。自己也确实不太清楚怎么回事,现在来研究一下。 什么是深浅拷贝 浅拷贝:指针拷贝,不会...

  • 深浅拷贝

    概念: 浅复制:不拷贝对象本身,仅仅是拷贝指向对象的指针深复制:是直接拷贝整个对象内存到另一块内存中 注意:这里有...

网友评论

      本文标题:深浅拷贝

      本文链接:https://www.haomeiwen.com/subject/jzgvcltx.html