美文网首页
iOS 深拷贝与浅拷贝

iOS 深拷贝与浅拷贝

作者: 拧发条鸟xds | 来源:发表于2018-09-09 13:48 被阅读0次
    本文参考

    博文配图
    容器类和非容器类
    1. 容器类:数组、字典、集合等。

      • 容器类不可变对象: 比如NSArray
      • 容器类可变对象: 比如NSMutableArray
    2. 非容器类:字符串

      • 非容器类不可变对象,比如NSString
      • 非容器类可变对象:比如NSMutableString

    初步解释
    1. 非容器类。

      • 浅拷贝:拷贝地址(对非容器类的浅拷贝就是拷贝对象的地址,对象里面存的内容仍然是一份,没有新的内存被分配。)
      • 深拷贝:拷贝内容(对非容器类的深拷贝就是重新分配一块内存,然后把另一个对象的内容原封不动的给我拿过来。)
    2. 容器类

      • 浅拷贝:生成一个新的容器(也就是“壳”),但是里面保存的元素的指针还是指向原来的元素地址。也就是说,对于容器类的浅拷贝来说,容器的地址是不同的,但是里面的内容地址是相同的,修改其中一个的内容,会使另一个的也跟着变化。(容器类的浅拷贝是对容器里的内容不进行拷贝,两个容器的地址是不同的,但容器里的所装的东西是一样的,在一个容器中修改值,则另一个浅拷贝的容器中的值也会变化。)
      • 深拷贝:不光生成一个新的容器,对容器里面的元素也进行拷贝。
    image
    immutableObject、mutableObject

    immutableObject,不可变对象如:NSString,NSArray等
    mutableObject,可变对象例如:NSMutableString,NSMutableArray等


    copy 和 mutablecopy

    ****copy 和 mutablecopy主要是为了生成对象的副本来使用****。

    • copy:copy出来的对象类型总是不可变的(例如, NSString, NSDictionary, NSArray等等)。

    • mutablecopy:mutableCopy拷贝出来的对象类型总是可变类型(例如, NSMutableString, NSMutableDictionary, NSMutableArray等等)

    注意:产生一个对象的可变副本并不要求被复制的对象是可变的,同理,可变对象也可以创建一个不可变副本。也就是说,mutableCooy和copy对于不可变对象和可变对象都可以使用。

    1.对于非容器类(非集合类)对象
    • 对于不可变对象(immutableObject)

      • copy,浅拷贝(指针拷贝)。返回的是一个不可变类型的对象。(只有这一个是浅拷贝,不可变对象的copy)
      • mutableCopy,深拷贝(内容拷贝)。返回的是一个可变类型的对象。
    • 对于可变对象(mutableObject)

      • copy,深拷贝(内容拷贝)。返回的是一个不可变类型的对象。
      • mutableCopy,深拷贝(内容拷贝)。返回的是一个可变类型的对象。
    [immutableObject copy]          //浅拷贝
    [immutableObject mutableCopy]   //深拷贝
    [mutableObject copy]            //深拷贝
    [mutableObject mutableCopy]     //深拷贝
    
    2.对于容器类(集合类)对象
    • 对于不可变对象(immutableObject)

      • copy,浅拷贝(指针拷贝)。返回的是一个不可变类型的对象。(只有这一个是浅拷贝,不可变对象的copy)
      • mutableCopy,深拷贝(内容拷贝)。返回的是一个可变类型的对象。
    • 对于可变对象(mutableObject)

      • copy,深拷贝(内容拷贝)。返回的是一个不可变类型的对象。
      • mutableCopy,深拷贝(内容拷贝)。返回的是一个可变类型的对象。

    用代码简单表示如下:(注意,容器类的浅拷贝是容器新生成,里面的元素还是指向原来的)

    [immutableObject copy]          //浅拷贝
    [immutableObject mutableCopy]   //深拷贝
    [mutableObject copy]            //深拷贝
    [mutableObject mutableCopy]     //深拷贝
    
    strong和copy的代码测试
    • copy只能修饰不可变类型,当修饰可变类型时,编译虽然不会出错,但是copy出来的是一个不可变类型对象,它被赋值给一个可变类型对象,当调用其方法修改其内容时会崩溃。
    • 注意:*NSString,对不可变类型的指针重新赋值,会改变其地址。NSString str = @"xxxxxx";//地址为0x100001050;str = @"ssssss";//地址为0x1000010d0
    • 所以说,如果用strong修饰NSString,赋值的来源是不可变(NSString)的话,即使赋值来源的内容被更改了,也不会影响被赋值的NSString对象;copy也是如此,虽然对于赋值来源是不可变(NSString)的拷贝是浅拷贝,但即使赋值来源的内容改变了,也不会有影响。因为赋值来源会重新指向一个地址,不是在原地址上更改内容。
    @interface Kaobei : NSObject
    @property (strong,nonatomic) NSString *strStrong;
    @property (copy,nonatomic) NSString *strCopy;
    @end
    @implementation Kaobei
    
    - (void)test{
        
        NSString *str = @"xxxxxx";
        
        self.strStrong = str;
        
        self.strCopy = str;
        
        NSLog(@"str = %p",str);             //str = 0x100001050
        NSLog(@"strStrong = %p",_strStrong);//strStrong = 0x100001050
        NSLog(@"strCopy = %p",_strCopy);    //strCopy = 0x100001050
        
        str = @"ssssss";
        
        NSLog(@"str = %p",str);             //str = 0x1000010d0
        NSLog(@"strStrong = %p",_strStrong);//strStrong = 0x100001050
        NSLog(@"strCopy = %p",_strCopy);    //strCopy = 0x100001050
    
    }
    
    @end
    
    
    使用copy而不用strong的原因

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

    关于retain和copy、mutableCopy的异同点
    1. retain:始终是浅拷贝。引用计数每次加一。返回对象是否可变与被复制的对象保持一致。

    2. copy:对于可变对象为深拷贝,引用计数不改变对于不可变对象是浅拷贝,引用计数每次加一。始终返回一个不可变对象。

    3. mutableCopy:始终是深拷贝,引用计数不改变。始终返回一个可变对象。

    自定义类对象之间的深浅拷贝问题

    在Objective-C中并不是所有的类都支持拷贝;只有遵循NSCopying协议的类,才支持copy拷贝,只有遵循NSMutableCopying协议的类,才支持mutableCopy拷贝。如果没有遵循拷贝协议,拷贝时会出错。

    如果我们想再我们自定义的类中支持copy和mutableCopy那么我们就需要使我们定义的类遵循NSCopying和NSMutableCopying协议,代码如下:

    @interface Test : NSObject <NSCopying, NSMutableCopying>
    

    然后再重写-(id) copyWithZone : (NSZone *) zone 和 -(id)mutableCopyWithZone : (NSZone *) zone

    重写-(id) copyWithZone :(NSZone *)zone方法如下

    //浅拷贝
    -(id) copyWithZone : (NSZone *) zone
    {
        return [self retain];     
    }
     
     
    //深拷贝
    -(id) mutableCopyWithZone : (NSZone *) zone
    {
        Test *test = [[Test allocWithZone : zone] init];
        test.property = self.property;
        return test;   
    

    相关文章

      网友评论

          本文标题:iOS 深拷贝与浅拷贝

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