iOS copy与mutableCopy

以前只知道copy操作过的对象,会得出一个新的不可变对象而mutableCopy操作过的对象,会得出一个新的可变对象,这篇文章算是对自己的误区的一个纠正,也是一个总结吧!

Copying Collections

拷贝分为深拷贝和浅拷贝;
深拷贝又分为完全拷贝和单层深拷贝;

浅拷贝(shallow copy)

浅拷贝指的是只拷贝对象的引用,而引用所指向的对象地址没有变还是同一个,只是对象的引用计数器+1了。

NSArray *array = @[@"1", @"2", @"3"];
NSArray *array2 = [array copy];

深拷贝(shallow copy)

完全拷贝()

完全深拷贝指的是当拷贝对象为集合时,即拷贝对象的地址,又拷贝对象内元素对象的地址;

NSMutableArray *array = [[NSMutableArray alloc] initWithArray:aarray copyItems:YES];

单层深拷贝(one-level-deep copy)

单层深拷贝指的是只对拷贝集合对象的地址,没有拷贝集合内元素对象的地址。对此,苹果官网文档有这样一句话描述:

This kind of copy is only capable of producing a one-level-deep copy.
If you only need a one-level-deep copy, you can explicitly call for one as in Listing 2.

NSArray *array = @[self.string1, self.string2, self.string3];
NSArray *barray = [array copy];

非集合对象的深拷贝与浅拷贝

不可变对象(以NSString为例)

先看一个示例:

    NSString *a = @"a";
    NSString *b = [a copy];
    NSMutableString *c = [a mutableCopy];
    
    NSLog(@"A:%p", a);
    NSLog(@"B:%p", b);
    NSLog(@"C:%p", c);

结果:

    A:0x100440078
    B:0x100440078
    C:0x60000025a910

不可变对象进行copy操作时,实质上是进行的浅拷贝操作,并没有产生新对象;不可变对象进行mutableCopy操作时,实质上是进行的深拷贝操作,并产生了新的可变对象。个人对不可变对象copy操作的理解,因为对象是不可改变的没有必要copy时产生一个新对象,同时也节约了内存空间。

不可变对象(以NSMutableString为例)

示例:

    NSMutableString *a = [NSMutableString stringWithFormat:@"a"];
    NSString *b = [a copy];
    NSMutableString *c = [a mutableCopy];
    
    NSLog(@"A:%p", a);
    NSLog(@"B:%p", b);
    NSLog(@"C:%p", c);

结果:

    A:0x6040000541c0
    B:0xa000000000000611
    C:0x604000055150

可变对象进行copy操作,实质上是进行了深拷贝操作,并产生了新的不可变对象;可变对象进行mutableCopy操作,实质上也是进行了深拷贝操作,并产生了新的可变对象;

总结:
copy对象是不可变对象时,执行的是浅拷贝操作,当对象是可变对象时,执行的是深拷贝操作;而mutableCopy操作都是进行的深拷贝操作。

集合对象的深拷贝与浅拷贝

不可变对象(以NSArray为例)

示例:

    NSArray *aarray = @[self.string1, self.string2, self.string3];
    NSArray *barray = [aarray copy];
    NSMutableArray *carray = [aarray mutableCopy];
    NSMutableArray *darray = [[NSMutableArray alloc] initWithArray:aarray copyItems:YES];

    NSLog(@"Aarray:%p", aarray);
    NSLog(@"Barray:%p", barray);
    NSLog(@"Carray:%p", carray);
    NSLog(@"Darray:%p", darray);
    
    for (NSString *i in aarray) {
        NSLog(@"subA--:%p", i);
    }
    
    for (NSString *i in barray) {
        NSLog(@"subB--:%p", i);
    }
    
    for (NSString *i in carray) {
        NSLog(@"subC--:%p", i);
    }
    
    for (NSString *i in darray) {
        NSLog(@"subD--:%p", i);
    }

结果:

    Aarray:0x604000452c60
    Barray:0x604000452c60
    Carray:0x604000452c00
    Darray:0x604000453fb0

    subA--:0x60400044dd40
    subA--:0x604000450320
    subA--:0x604000452d80

    subB--:0x60400044dd40
    subB--:0x604000450320
    subB--:0x604000452d80

    subC--:0x60400044dd40
    subC--:0x604000450320
    subC--:0x604000452d80

    subD--:0xa000000000000611
    subD--:0xa000000000000621
    subD--:0xa000000000000631

当对不可变集合对象进行copy操作时,只是拷贝了集合对象的指针,并没有对对象的地址进行拷贝,也没有对对象内的元素进行拷贝;当对不可变集合对象进行mutableCopy操作时,拷贝了对象的地址,但是没有对对象内的元素对象地址进行拷贝;当对不可变集合对象进行initWithArray:copyItems:操作时,通过重新创建集合对象,设置copyItemsYES,对集合内的元素对象进行了拷贝。

可变对象(以NSMutableArray为例)

示例:

    NSMutableArray *aarray = [NSMutableArray arrayWithObjects:self.string1, self.string2, self.string3, nil];
    NSArray *barray = [aarray copy];
    NSMutableArray *carray = [aarray mutableCopy];
    NSMutableArray *darray = [[NSMutableArray alloc] initWithArray:aarray copyItems:YES];
    
    NSLog(@"Aarray:%p", aarray);
    NSLog(@"Barray:%p", barray);
    NSLog(@"Carray:%p", carray);
    NSLog(@"Darray:%p", darray);
    
    for (NSString *i in aarray) {
        NSLog(@"subA--:%p", i);
    }
    
    for (NSString *i in barray) {
        NSLog(@"subB--:%p", i);
    }
    
    for (NSString *i in carray) {
        NSLog(@"subC--:%p", i);
    }
    
    for (NSString *i in darray) {
        NSLog(@"subD--:%p", i);
    }

结果:

    Aarray:0x60000025c140
    Barray:0x60000025ac10
    Carray:0x600000259ad0
    Darray:0x600000258d50

    subA--:0x604000251df0
    subA--:0x604000251cd0
    subA--:0x604000251610

    subB--:0x604000251df0
    subB--:0x604000251cd0
    subB--:0x604000251610

    subC--:0x604000251df0
    subC--:0x604000251cd0
    subC--:0x604000251610

    subD--:0xa000000000000611
    subD--:0xa000000000000621
    subD--:0xa000000000000631

当对可变集合对象进行copy操作时,对对象的地址进行拷贝,但没有对对象内的元素进行拷贝;当对可变集合对象进行mutableCopy操作时,拷贝了对象的地址,但是没有对对象内的元素对象地址进行拷贝;当对可变集合对象进行initWithArray:copyItems:操作时,通过重新创建集合对象,设置copyItemsYES,对集合内的元素对象进行了拷贝。

你可能感兴趣的:(iOS copy与mutableCopy)