美文网首页iosiOS好文收藏
NSString NSArray的copy和mutableCop

NSString NSArray的copy和mutableCop

作者: KardelShaw | 来源:发表于2016-12-03 17:45 被阅读0次

    浅复制——即指针复制,不创建新的对象;
    深复制——即内容复制,创建一个新的对象。
    (这么精辟的话当然出自高手之口)
    引自:http://www.jianshu.com/p/ebbac2fec4c6

    1 NSString和NSMutableString

    (1) NSString发送copy消息时会进行浅复制:

    NSString *name = @"name";
    NSString *nameFromCopy = [name copy];
    NSLog(@"%p", name);
    NSLog(@"%p", nameFromCopy);
    
    [2283:101871] 0x1000020b0
    [2283:101871] 0x1000020b0
    

    看上去对NSString的copy好像什么都没做,实际上是有的,ARC会在后台调用retain给这个字符串添加一个引用计数。

    (2)NSString发送mutableCopy消息是深复制:

    NSString *name = @"name";
    NSString *nameFromCopy = [name mutableCopy];
    NSLog(@"%p", name);
    NSLog(@"%p", nameFromCopy);
    
    [2743:131031] 0x1000020b0
    [2743:131031] 0x100700200
    

    (3) 向NSMutableString发送copy消息会进行深复制:

    NSMutableString *name = [[NSMutableString alloc] initWithString:@"name"];
    NSString *nameFromCopy = [name copy];
    NSLog(@"%p", name);
    NSLog(@"%p", nameFromCopy);
    
    [2270:97375] 0x100100540
    [2270:97375] 0x656d616e45
    

    (4) NSMutableString的mutableCopy消息是深复制:

    NSMutableString *name = [[NSMutableString alloc] initWithString:@"name"];
    NSString *nameFromCopy = [name mutableCopy];
    NSLog(@"%p", name);
    NSLog(@"%p", nameFromCopy);
    
    
    [2753:133279] 0x1005034d0
    [2753:133279] 0x100503650
    

    小结:

    Numbers制表

    2 NSArray和NSMutableArray

    (1) NSArray的copy是浅复制

    NSArray *array = [[NSArray alloc] init];
    NSArray *arrayFromCopy = [array copy];
    NSLog(@"%p", array);
    NSLog(@"%p", arrayFromCopy);
    
    [2798:141184] 0x100501360
    [2798:141184] 0x100501360
    

    (2)NSMutable的copy是深复制

    NSMutableArray *array = [[NSMutableArray alloc] init];
    NSArray *arrayFromCopy = [array copy];
    NSLog(@"%p", array);
    NSLog(@"%p", arrayFromCopy);
    
    [2871:152574] 0x100700420
    [2871:152574] 0x100501360
    

    (3)NSArray的mutableCopy是深复制

    NSArray *array = [[NSArray alloc] init];
    NSArray *arrayFromCopy = [array mutableCopy];
    NSLog(@"%p", array);
    NSLog(@"%p", arrayFromCopy);
    
    [2881:155075] 0x100201360
    [2881:155075] 0x100700a90
    

    (4)NSMutableArray的mutableCopy是深复制

    NSMutableArray *array = [[NSMutableArray alloc] init];
    NSArray *arrayFromCopy = [array mutableCopy];
    NSLog(@"%p", array);
    NSLog(@"%p", arrayFromCopy);
    
    [2891:156290] 0x1007001e0
    [2891:156290] 0x100700380
    

    也就是说,得出了跟NSString和NSMutableString之间一样的结论??

    Numbers制表

    表面上来看,确实是这样。但是,数组作为一个容器,肯定还要考虑里面的数据情况。我们尝试在数组里放点实验数据,比如几个字符串:
    NSArray的copy:

    //创建3个可变字符串
    NSMutableString *string1 = [NSMutableString stringWithFormat:@"a"];
    NSMutableString *string2 = [NSMutableString stringWithFormat:@"b"];
    NSMutableString *string3 = [NSMutableString stringWithFormat:@"c"];
    //将3个字符串放入数组中
    NSArray *array = [NSArray arrayWithObjects:string1, string2, string3, nil];
    NSArray *arrayFromCopy = [array copy];
    NSLog(@"%p", array);                //输出原数组及其元素的地址
    NSLog(@"%p", array[0]);
    NSLog(@"%p", array[1]);
    NSLog(@"%p", array[2]);
    printf("\n");
    NSLog(@"%p", arrayFromCopy);        //输出copy的数组及其元素的地址
    NSLog(@"%p", arrayFromCopy[0]);
    NSLog(@"%p", arrayFromCopy[1]);
    NSLog(@"%p", arrayFromCopy[2]);
    
    [3141:182137] 0x100701030
    [3141:182137] 0x100700200
    [3141:182137] 0x1007003e0
    [3141:182137] 0x100700440
    
    [3141:182137] 0x100701030
    [3141:182137] 0x100700200
    [3141:182137] 0x1007003e0
    [3141:182137] 0x100700440
    

    NSArray的mutableCopy

    NSArray *array = [NSArray arrayWithObjects:string1, string2, string3, nil];
    NSArray *arrayFromCopy = [array mutableCopy];
    NSLog(@"%p", array);          //输出原数组及其元素的地址
    NSLog(@"%p", array[0]);
    NSLog(@"%p", array[1]);
    NSLog(@"%p", array[2]);
    printf("\n");
    NSLog(@"%p", arrayFromCopy);        //输出copy的数组及其元素的地址
    NSLog(@"%p", arrayFromCopy[0]);
    NSLog(@"%p", arrayFromCopy[1]);
    NSLog(@"%p", arrayFromCopy[2]);
    
    [3151:184027] 0x100103410
    [3151:184027] 0x1001024d0
    [3151:184027] 0x100102390
    [3151:184027] 0x1001023d0
    
    [3151:184027] 0x100102bf0
    [3151:184027] 0x1001024d0
    [3151:184027] 0x100102390
    [3151:184027] 0x1001023d0
    

    所以,其实NSArray的mutableCopy只是对数组对象进行了深复制,而数组内元素依然是浅复制。像下图这样:

    Numbers绘图

    事实上NSMutableArray的copy和mutableCopy也是这样,为了节省篇幅我就不放代码了,有兴趣的朋友可以自己试一下。

    如果想实现数组内元素也进行深复制,有个比较简单的方法,就是用NSArray提供的一个初始化方法
    -(instancetype)initWithArray:copyItems:

    NSArray *array = [NSArray arrayWithObjects:string1, string2, string3, nil];
    NSArray *arrayFromCopy = [[NSArray alloc] initWithArray:array copyItems:YES];
    NSLog(@"%p", array);               //输出原数组及其元素的地址
    NSLog(@"%p", array[0]);
    NSLog(@"%p", array[1]);
    NSLog(@"%p", array[2]);
    printf("\n");
    NSLog(@"%p", arrayFromCopy);        //输出copy的数组及其元素的地址
    NSLog(@"%p", arrayFromCopy[0]);
    NSLog(@"%p", arrayFromCopy[1]);
    NSLog(@"%p", arrayFromCopy[2]);
    
    [3166:189328] 0x100106fc0
    [3166:189328] 0x100100270
    [3166:189328] 0x100105eb0
    [3166:189328] 0x100105f10
    
    [3166:189328] 0x100106d90
    [3166:189328] 0x6115
    [3166:189328] 0x6215
    [3166:189328] 0x6315
    

    现在引用情况像这样:


    Numbers绘图

    我猜你现在肯定很想知道,下面这种情况的话,用上面的深复制方法能否奏效:(模仿歪果仁的口吻,听起来就像是一个很牛逼的人在说话一样)

    Numbers绘图
    //创建3个可变字符串
    NSMutableString *string1 = [NSMutableString stringWithFormat:@"a"];
    NSMutableString *string2 = [NSMutableString stringWithFormat:@"b"];
    NSMutableString *string3 = [NSMutableString stringWithFormat:@"c"];
           
    //将string1放入数组array_0中
    NSArray *array_0 = [[NSArray alloc] initWithObjects:string1, nil];
    //将array_0,string2,string3放入数组array中
    NSArray *array = [NSArray arrayWithObjects:array_0, string2, string3, nil];
    //复制�数组
    NSArray *arrayFromCopy = [[NSArray alloc] initWithArray:array copyItems:YES];
    //输出
    NSLog(@"%p", array);          //输出原数组及其元素的地址
    NSLog(@"%p", array[0]);
    NSLog(@"%p", array[1]);
    NSLog(@"%p", array[2]);
    printf("\n");
    NSLog(@"%p", arrayFromCopy);    //输出copy的数组及其元素的地址
    NSLog(@"%p", arrayFromCopy[0]);
    NSLog(@"%p", arrayFromCopy[1]);
    NSLog(@"%p", arrayFromCopy[2]);
    printf("\n");
    NSLog(@"%p", array[0][0]);   //输出原数组和copy数组的数组的字符串string1地址
    NSLog(@"%p", arrayFromCopy[0][0]);
    
    [3203:205170] 0x100106ef0
    [3203:205170] 0x1001069b0
    [3203:205170] 0x100100200
    [3203:205170] 0x100100260
    
    [3203:205170] 0x100106f20
    [3203:205170] 0x1001069b0
    [3203:205170] 0x6215
    [3203:205170] 0x6315
    
    [3203:205170] 0x1001062f0
    [3203:205170] 0x1001062f0
    

    这就是答案:


    Numbers绘图

    可见NSArray的实例方法-(instancetype)initWithArray:copyItems:的深复制到三维数组已经力不从心了,如果想对三维或以上的数组进行彻底深复制,就必须使用杀手锏——归档。
    关于归档,笔者另文:http://www.jianshu.com/p/a0b994d34c0a

    这2篇文章循环引用了:)

    相关文章

      网友评论

        本文标题:NSString NSArray的copy和mutableCop

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