iOS 深拷贝浅拷贝

之前除了面试中会被问道类似这样的问题,平时工作中没有特别注意过这个深拷贝浅拷贝有啥影响,直到项目中出现了问题,才高度重视起来,那么重新认识一下深浅拷贝吧。

事情是这样的,我需要两个数组,一个数组存放源数据,另一个数组存放源数据基础上会变动的数据。这两数组都定义成了可变数

@property (nonatomic, strong) NSMutableArray *dataArray;
@property (nonatomic, strong) NSMutableArray *dataArray_ori;

初始化,赋值

for (NSDictionary *cellDic in remodel.data[@"list"]) {
     [self.existedNovelIdsArray addObject:cellDic[@"novel_id"]];
     [self.dataArray addObject:cellDic];
     [self.dataArray_ori addObject:cellDic];
     [self.foldStatusArray addObject:@1];
  }

赋值的时候,断点查看这两数组里元素的地址,发现是同一个地址

然后数据发生了变动,dataArray里的数据需要有修改

NSMutableDictionary *cellDic = self.dataArray[idxP.row];
cellDic[@"list_remark"] = text;
[self.dataArray replaceObjectAtIndex:idxP.row withObject:[cellDic mutableCopy]];

这样修改dataArray的数据的话,会发现第一次修改的时候,dataArray_ori的数据也跟着变了,第二次源数据没问题。以下是断点截图:

由断点可知道,取出来的元素内存地址是最开始存值的时候一个地址,所以这个地址的对象变了之后,dataArray和dataArray_ori里对应的元素也变了,因为这两数组里的元素指向的都是这个地址。

换成以下方式可以解决源数据被改变的问题,当然还有其他的方法,这里只拿出这一种

NSMutableDictionary *cellDic = [self.dataArray[idxP.row] mutableCopy];

cellDic[@"list_remark"] = text;
[self.dataArray replaceObjectAtIndex:idxP.row withObject:cellDic];

 用到了深拷贝,分配了新的内存地址给cellDic,然后修改cellDic,不会影响到原来源数组里的元素。

在这里记录一下,权当笔记,加深印象:

  • 深拷贝:内容拷贝,会开辟新的内存空间;
  • 浅拷贝:只是指针的拷贝,原对象和新的复制的对象都指向同一地址,不会开辟新的内存空间。

为了加深印象,可以看一下Demo:

    NSMutableArray *mutArr = [NSMutableArray arrayWithArray:@[@"1"]];
    NSArray *arrary = @[@"2"];
    
    NSMutableArray *arr1 = mutArr.copy;
//    [arr1 replaceObjectAtIndex:0 withObject:@[@"haha"]];
    NSMutableArray *arr2 = mutArr.mutableCopy;
    
    NSMutableArray *arr3 = arrary.copy;
//    [arr3 replaceObjectAtIndex:0 withObject:@[@"haha"]];
    NSMutableArray *arr4 = arrary.mutableCopy;
    [arr4 replaceObjectAtIndex:0 withObject:@[@"haha"]];

断点查看内存地址:

 copy和mutableCopy的区别:

  • 用copy做拷贝,不管是对可变对象还是不可变对象,得到的都是不可变对象;
  • 用mutableCopy做拷贝,不管是对可变对象还是不可变对象,得到的都是可变对象;

  • 不可变对象用copy拷贝,属于浅拷贝,与被拷贝对象共用的是同一个内存空间,不会新开辟一个新的内存地址。
  • 可变对象不管用copy还是mutableCopy,都属于深拷贝,会为拷贝出的内容开辟一个新的内存空间。

补充一下,既然用copy对不可变对象做拷贝是浅拷贝,那是不是对这两其中一个对象做改变,另一个对象就会跟着变呢?也就是说我改变一下上面例子里的array的值,那arr3是不是也会跟着变呢?看下面的操作:

 发现改变了array的值,会被开辟新的内存空间,所以arr3没有变。

猜你喜欢

转载自blog.csdn.net/jdd92/article/details/124726736