分享链接 http://www.jianshu.com/p/4e327d1832ef

       分享链接2 iOS 深拷贝   和 浅拷贝

      https://github.com/ChenYilong/iOSInterviewQuestions/blob/master/01%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88/%E3%80%8A%E6%8B%9B%E8%81%98%E4%B8%80%E4%B8%AA%E9%9D%A0%E8%B0%B1%E7%9A%84iOS%E3%80%8B%E9%9D%A2%E8%AF%95%E9%A2%98%E5%8F%82%E8%80%83%E7%AD%94%E6%A1%88%EF%BC%88%E4%B8%8A%EF%BC%89.md

Copy 与 Strong 关键字的区别

   1. copy 关键字 一般用来修饰 NSString , NSArray, NSDictionary  这些不可变 immutable CF(Core foundation) 对象

      要理解多态 ,父类指针可以指向子类对象, 还有 NSRuntime 的这个 C 库的实现机制;

     因为父类指针可以指向子类对象,使用 copy 的目的是为了让本对象的属性不受外界影响,使用 copy 无论给我传入是一个可变对象还是不可对象,

    我本身持有的就是一个不可变的副本.这个时候我有一个不可变的副本在堆里面了;

 2.如果我们使用是 strong ,那么这个属性就有可能指向一个可变对象,如果这个可变对象在外部被修改了,那么会影响该属性.
copy 此特质所表达的所属关系与 strong 类似。然而设置方法并不保留新值,而是将其“拷贝” (copy)。 当属性类型为 NSString 时,经常用此特质来保护其封装性,因为传递给设置方法的新值有可能指向一个 NSMutableString 类的实例。这个类是 NSString 的子类,表示一种可修改其值的字符串,此时若是不拷贝字符串,那么设置完属性之后,字符串的值就可能会在对象不知情的情况下遭人更改。所以,这时就要拷贝一份“不可变” (immutable)的字符串,确保对象中的字符串值不会无意间变动。只要实现属性所用的对象是“可变的” (mutable),就应该在设置新属性值时拷贝一份。

   NSArray  我们知道他是一个不可变的容器;  我们使用它的初衷也是希望数据的指针绑定在不可变的容器;

但是如果仍然使用的是 Strong 指针, 有可能存在的情况是 , 在你不知情的情况, 数组里面的元素确实变了; 这往往是我们不想要的;

@property (nonatomic ,readwrite, strong) NSArray *array;

然后进行下面的操作:

      NSMutableArray *mutableArray = [[NSMutableArray alloc] initWithObjects:@11,@12, nil];
        self.array = mutableArray;
        [mutableArray removeAllObjects];
        NSLog(@"first:%@",self.array);
        
        NSArray *array = @[ @1, @2, @3, @4 ];
        [mutableArray addObjectsFromArray:array];
        self.array = [mutableArray copy];
          NSLog(@"second:%@",self.array);
        [mutableArray removeAllObjects];
        NSLog(@"third:%@",self.array);

打印结果如下所示:copy 修饰结果

first:(
    11,
    12
)
2016-02-28 13:20:31.524 TestJellyPath[17203:899296] second:(
    1,
    2,
    3,
    4
)
2016-02-28 13:20:31.524 TestJellyPath[17203:899296] third:(
    1,
    2,
    3,
    4
)

strong 修饰 打印如下:

first:(

)
2016-02-28 13:20:31.524 TestJellyPath[17203:899296] second:(
    1,
    2,
    3,
    4
)
2016-02-28 13:20:31.524 TestJellyPath[17203:899296] third:(
    1,
    2,
    3,
    4
)

可以 看到 strong 修饰 部分 指针指向内容确实是可变 的 , 而经过 [
mutableArray
   copy] 方法的调用(递归调用 copyWithZone)之后 , 又重新 copy 了一份不可变的内容 到堆里

为了理解这种做法,首先要知道,两种情况:
对非集合类对象的 copy 与 mutableCopy 操作;
对集合类对象的 copy 与 mutableCopy 操作。

  1. 对非集合类对象的copy操作:

在非集合类对象中:对 immutable 对象进行 copy 操作,是指针复制,mutableCopy 操作时内容复制;对 mutable 对象进行 copy 和 mutableCopy 都是内容复制。用代码简单表示如下:

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

比如以下代码:

NSMutableString *string = [NSMutableString stringWithString:@"origin"];//copy
NSString *stringCopy = [string copy];

查看内存,会发现 string、stringCopy 内存地址都不一样,说明此时都是做内容拷贝、深拷贝。即使你进行如下操作:

[string appendString:@"origion!"]

stringCopy 的值也不会因此改变,但是如果不使用 copy,stringCopy 的值就会被改变。 集合类对象以此类推。 所以,

用 @property 声明 NSString、NSArray、NSDictionary 经常使用 copy 关键字,是因为他们有对应的可变类型:NSMutableString、NSMutableArray、NSMutableDictionary,他们之间可能进行赋值操作,为确保对象中的字符串值不会无意间变动,应该在设置新属性值时拷贝一份。

2、集合类对象的copy与mutableCopy

集合类对象是指 NSArray、NSDictionary、NSSet ... 之类的对象。下面先看集合类immutable对象使用 copy 和 mutableCopy 的一个例子:

NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"]];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];

查看内容,可以看到 copyArray 和 array 的地址是一样的,而 mCopyArray 和 array 的地址是不同的。说明 copy 操作进行了指针拷贝,mutableCopy 进行了内容拷贝。但需要强调的是:此处的内容拷贝,仅仅是拷贝 array 这个对象,array 集合内部的元素仍然是指针拷贝。这和上面的非集合 immutable 对象的拷贝还是挺相似的,那么mutable对象的拷贝会不会类似呢?我们继续往下,看 mutable 对象拷贝的例子:

NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];

查看内存,如我们所料,copyArray、mCopyArray和 array 的内存地址都不一样,说明 copyArray、mCopyArray 都对 array 进行了内容拷贝。同样,我们可以得出结论:

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

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

其实对 集合对象的深拷贝 , 也可以理解为 对这个指针指向部分的右值的 copy ; 这个c语言里面的内容;




Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐