美文网首页iOS_Skill_CollectiOS 知识点iOS 面试题
在iOS中关于深拷贝和浅拷贝以及copy属性的理解

在iOS中关于深拷贝和浅拷贝以及copy属性的理解

作者: 苍茫的天涯 | 来源:发表于2017-04-11 21:01 被阅读1641次

    今天学习了一下iOS中关于深拷贝和浅拷贝的一些概念,感觉是真的绕,把我虎的一愣一愣的,更加加深了我对自己没有好好学习OC基础的鄙视,悲剧啊!言归正传,在一天的学习下来以后,总算对深拷贝和浅拷贝有了一些理解,这里就赶紧写下来加深印象。

    1:copy 和 mutablecopy

    1. copy拷贝出来的对象类型总是不可变类型(例如, NSString, NSDictionary, NSArray等等)
    2. mutableCopy拷贝出来的对象类型总是可变类型(例如, NSMutableString, NSMutableDictionary, NSMutableArray等等)
    下面用例子来简单解释一下
    NSString *str1 = @"我是字符串";
    NSString *str2 = [str1 copy];
    NSMutableString *str3 = [str1 mutableCopy];
    NSString *str4 = [str1 mutableCopy];
    
    (lldb) p str1
    (__NSCFConstantString *) $1 = 0x0000000105981060 @"我是字符串"
    (lldb) p str2
    (__NSCFConstantString *) $2 = 0x0000000105981060 @"我是字符串"
    (lldb) p str3
    (__NSCFString *) $3 = 0x000060000007edc0 @"我是字符串"
    (lldb) p str4
    (__NSCFString *) $4 = 0x000060000007ef40 @"我是字符串"
    

    这里需要解释一下,在runtime下NSString的“真身”是__NSCFConstantStringNSMutableString的“真身”是__NSCFString,然后我们就能很清楚的看到,只要是copy得到的值就是不可变类型,而mutablecopy得到的是可变类型。

    2:深拷贝和浅拷贝

    用一张图来介绍一下:

    深拷贝和浅拷贝.png

    这里先描述一下两个概念,一个是immutableObject【不可变对象如:NSStringNSArray等】,另一个是mutableObject【可变对象例如:NSMutableString,NSMutableArray等】;

    在非集合类对象中:

    对 immutable 对象进行 copy 操作,是指针复制【浅拷贝】,mutableCopy 操作时内容复制【深拷贝】;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。用代码简单表示如下:

    • [immutableObject copy] // 浅复制
    • [immutableObject mutableCopy] //深复制
    • [mutableObject copy] //深复制
    • [mutableObject mutableCopy] //深复制

    下面用例子展示一下:

    NSString *str1 = @"我是字符串";
    NSString *str2 = [str1 copy];
    NSMutableString *str3 = [str1 mutableCopy];
        
    NSMutableString *mutableStr1 = [NSMutableString stringWithString:@"我也是字符串"];
    NSString *mutableStr2 = [mutableStr1 copy];
    NSMutableString *mutableStr3 = [mutableStr1 mutableCopy];
    

    然后用debug模式下,把这两个字符串p出来

    (lldb) p str1
    (__NSCFConstantString *) $0 = 0x000000010d5c6060 @"我是字符串"
    (lldb) p str2
    (__NSCFConstantString *) $1 = 0x000000010d5c6060 @"我是字符串"
    (lldb) p str3
    (__NSCFString *) $2 = 0x000061800026c340 @"我是字符串"
    (lldb) p mutableStr1 
    (__NSCFString *) $3 = 0x000061800026c4c0 @"我也是字符串"
    (lldb) p mutableStr2
    (__NSCFString *) $4 = 0x00006180000555a0 @"我也是字符串"
    (lldb) p mutableStr3
    (__NSCFString *) $5 = 0x000061800026c100 @"我也是字符串"
    

    可以看出,除了对immutable的Copy动作得到的string是浅拷贝外,其他的都是深拷贝。

    在集合类对象中:

    对 immutable 对象进行 copy,是指针复制【浅拷贝】, mutableCopy 是内容复制【深拷贝】;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。但是:集合对象的内容复制仅限于对象本身,对象元素仍然是指针复制。用代码简单表示如下:

    • [immutableObject copy] // 浅复制
    • [immutableObject mutableCopy] //单层深复制
    • [mutableObject copy] //单层深复制
    • [mutableObject mutableCopy] //单层深复制

    这里说的单层深复制其实就是所谓的不完全深拷贝,这个跟Java中的深拷贝概念又有所区别,iOS中集合对象的“深拷贝”只拷贝了一个壳,对于壳内的元素是浅拷贝,和java中递归的深拷贝有所不同。

    3:property中的copy属性

    了解完上面说的copy和mutablecopy,就可以讲讲property中的copy属性了。简单的用几行代码来表示copy属性的意思的话,就是下面这样:

    @property (copy, nonatomic) NSString *someString;
    
    - (void)setSomeString:(NSString *)someString
    {
      //没有写copy属性时
      _someString = someString;
      //写了copy属性时
      _someString = [someString copy];
    }
    

    下面是摘自《招聘一个靠谱的 iOS》

    1. 因为父类指针可以指向子类对象,使用 copy 的目的是为了让本对象的属性不受外界影响,使用 copy 无论给我传入是一个可变对象还是不可对象,我本身持有的就是一个不可变的副本.
    2. 如果我们使用是 strong ,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性.

    也就是说,当你加上一个copy属性时,这个对象在被set的时,就不再是改变这个对象的原有内存,而是修改这个对象的不可变副本内存。这样就能够保证这个元素不会被外部修改影响

    接下来用一个例子来解释一下:

    @property (nonatomic ,strong) NSArray *array;
    
    NSArray *array = @[ @1, @2, @3, @4 ];
    NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithArray:array];
    self.array = mutableArray;
    [mutableArray removeAllObjects];
    

    那么这个时候self.array的值到底是@[ @1, @2, @3, @4 ]还是一个空的的数组呢。下面是结果

    (lldb) po self.array
    <__NSArrayM 0x60800025a9d0>(
    
    )
    

    这就是property里不用copy而用strong的结果,当你确定这个元素是不可变的,那么copy属性还是很有必要的,不然在接下的代码中,你什么时候不小心把他改了你都不知道(╯‵□′)╯︵┻━┻

    相关文章

      网友评论

        本文标题:在iOS中关于深拷贝和浅拷贝以及copy属性的理解

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