IOS深浅拷贝的深入分析

2024-03-13 08:38
文章标签 ios 拷贝 深入分析 深浅

本文主要是介绍IOS深浅拷贝的深入分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Apple官方文档如下:https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Collections/Articles/Copying.html

最近用Core Data做数据管理,Fetch到NSArray类型的结果数组,为了能够进行增、删、改,我把它MutableCopy到一个NSMutableArray数组中。增加、删除用manageModelsContext中的接口操作即可,修改则把NSArray结果中需要修改的实例取出来进行更改,然后用manageModelsContext保存即可完成修改到sqlite文件。

可是问题是我发现用MutableCopy得到的数组中取出的元素直接修改后保存,也能完成修改操作。于是就产生了这样的一个疑问:MutableCopy是浅拷贝??再下来我就发现copy相关的东西我还完全没有搞清楚。

 

首先关于copy和mutableCopy的行为:不管是NSString这种元素类、还是NSArray这样的容器类、还是Mutable和非Mutable类,copy和mutableCopy调用后表现的行为到底是什么样完成取决于类本身NSCopying和NSMutableCopying协议是如何实现的。

想要正常调用copy和mutableCopy两个函数,那么类就一定要实现对应的协议。

1.      元素数据的copy和mutableCopy。

常用的NSString类,示例代码如下:

[cpp]  view plain copy
  1. NSString* string = @”a”;  
  2. NSString* stringCopy = [string copy];// stringCopy与string地址相同,retainCount+ 1  
  3. NSMutableString* stringMCopy = [string mutablecopy];// stringMCopy与string地址不同  
  4.    
  5. NSMutableString* stringM1 = [stringMCopy copy];//地址与stringMCopy不同,且为不可修改  
  6. NSMutableString* stringM2 = [stringMCopy mutablecopy];//地址与stringMCopy不同,可修改   

可以基本推出NSString和NSMutableString中两个协议的实现

 

[cpp]  view plain copy
  1. NSString:  
  2. - (id)copywithZone:(NSZone*)zone  
  3. {  
  4.   return self;  
  5. }  
  6.    
  7. - (id)mutableCopywithZone:(NSZone*)zone  
  8. {  
  9.   NSMutableString* copy =[[NSMutableString alloc] initxxxxxx];  
  10.   ....  
  11.   return copy;  
  12. }  
  13. NSMutableString:  
  14. - (id)copywithZone:(NSZone*)zone  
  15. {  
  16.   NSString* copy = [[NSStringalloc] initxxxxxx];  
  17.   ....  
  18.   return copy;//所以不可修改  
  19. }  
  20.    
  21. - (id)mutableCopywithZone:(NSZone*)zone  
  22. {  
  23.   NSMutableString* copy =[[NSMutableString alloc] initxxxxxx];  
  24.   ....  
  25.   return copy;  
  26. }  

2.      容器类的copy和mutableCopy。

常用类NSArray和NSMutableArray,看如下示例代码:

[cpp]  view plain copy
  1. Class1* obj1= ....;//正常初始化  
  2. NSArray* array = [[NSArray alloc] initWithObjects:obj1, nil];  
  3. NSArray* arrayCopy = [array copy];//地址不变,retaincount+1  
  4. NSMutableArray* arrayMCopy = [array mutableCopy];//地址改变,但是数组中成员指针和obj1相同,浅拷贝  
  5.   
  6. NSMutableArray* arrayM1 = [arrayMCopy Copy];//地址改变,但是数组中成员指针和obj1相同,浅拷贝。arrayM1为NSArray不可修改  
  7. NSMutableArray* arrayM2 = [arrayMCopy mutableCopy];//地址改变,但是数组中成员指针和obj1相同,浅拷贝  
[cpp]  view plain copy
  1. //推断  
[cpp]  view plain copy
  1. NSArray:  
  2. - (id)copywithZone:(NSZone*)zone  
  3. {  
  4.   //伪码  
  5.   return [self retain];  
  6. }  
  7.   
  8. - (id)mutableCopywithZone:(NSZone*)zone  
  9. {  
  10.   NSMutableArray* copy = [[NSMutableString alloc] initxxxxxx];  
  11.   for (id element in self) {  
  12.     [copy addObject:element];//element retian count + 1  
  13.     ....  
  14.   }  
  15.   return copy;  
  16. }  
  17.   
  18. NSMutableArray:  
  19. - (id)copywithZone:(NSZone*)zone  
  20. {  
  21.   NSArray* copy = [[NSArray alloc] initXXX];  
  22.   /*把每个element加入到copy数组,retainCount+1*/  
  23.   ....  
  24.   return copy;  
  25. }  
  26.   
  27. - (id)mutableCopywithZone:(NSZone*)zone  
  28. {  
  29.   NSMutableArray* copy = [[NSMutableString alloc] initxxxxxx];  
  30.   for (id element in self) {  
  31.     [copy addObject:element];//element retian count + 1  
  32.     ....  
  33.   }  
  34.   return copy;  
  35. }  

3.      深拷贝

上面提到的官方文档中介绍两种实现深拷贝的方法:

a.      用Array的initWithArray:  copyItems函数,如下:

NSArray *deepCopyArray=[[NSArray alloc] initWithArray: someArraycopyItems: YES];

调用后,会对原NSArray中的每个元素调用其copy函数,并把返回的id加入到新的数组中。所以这是依赖于Obj对象类实现的深拷贝,如果- (id)copywithZone:(NSZone*)zone是重新分配一块内存赋值后返回,那么就是真正的深拷贝。如果直接返回自身,那么它只是浅拷贝。

b.      用archiver方式:

NSArray* trueDeepCopyArray = [NSKeyedUnarchiverunarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject:oldArray]];

这是真正意义上的深拷贝,不依赖于实际类Copying协议的实现。

 

4. 用Category实现自定义的深拷贝deepmutableCopy,如:

[cpp]  view plain copy
  1. - (NSMutableArray *)mutableDeepCopy  
  2. {  
  3.     NSMutableArray *ret = [[NSMutableArrayalloc] initWithCapacity:[self count]];  
  4.     for (id value in self)  
  5.     {  
  6.         id oneCopy = nil;  
  7.         if ([value respondsToSelector:@selector(mutableDeepCopy)])  
  8.             oneCopy = [value mutableDeepCopy];  
  9.         else if ([value respondsToSelector:@selector(mutableCopy)])  
  10.             oneCopy = [value mutableCopy];  
  11.         if (oneCopy == nil)  
  12.             oneCopy = [value copy];  
  13.         [ret addObject: oneCopy];  
  14.     }  
  15.     return ret;  
  16. }  

这篇关于IOS深浅拷贝的深入分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/804261

相关文章

Java中ArrayList的8种浅拷贝方式示例代码

《Java中ArrayList的8种浅拷贝方式示例代码》:本文主要介绍Java中ArrayList的8种浅拷贝方式的相关资料,讲解了Java中ArrayList的浅拷贝概念,并详细分享了八种实现浅... 目录引言什么是浅拷贝?ArrayList 浅拷贝的重要性方法一:使用构造函数方法二:使用 addAll(

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

【iOS】MVC模式

MVC模式 MVC模式MVC模式demo MVC模式 MVC模式全称为model(模型)view(视图)controller(控制器),他分为三个不同的层分别负责不同的职责。 View:该层用于存放视图,该层中我们可以对页面及控件进行布局。Model:模型一般都拥有很好的可复用性,在该层中,我们可以统一管理一些数据。Controlller:该层充当一个CPU的功能,即该应用程序

Linux 使用rsync拷贝文件

显示进度条 rsync 可以显示进度条,您可以使用 --progress 或 -P 选项来显示每个文件的传输进度和已完成文件的统计信息。 显示进度条的常用选项: --progress 选项 使用 --progress 显示每个文件的传输进度信息:rsync -av --progress /src/ /dest/ -a:归档模式,表示递归拷贝并保持文件权限、时间戳等。-v:详细模式,显示更

python基础语法十一-赋值、浅拷贝、深拷贝

书接上回: python基础语法一-基本数据类型 python基础语法二-多维数据类型 python基础语法三-类 python基础语法四-数据可视化 python基础语法五-函数 python基础语法六-正则匹配 python基础语法七-openpyxl操作Excel python基础语法八-异常 python基础语法九-多进程和多线程 python基础语法十-文件和目录操作

插件maven-search:Maven导入依赖时,使用插件maven-search拷贝需要的依赖的GAV

然后粘贴: <dependency>    <groupId>mysql</groupId>    <artifactId>mysql-connector-java</artifactId>    <version>8.0.26</version> </dependency>

JS手写实现深拷贝

手写深拷贝 一、通过JSON.stringify二、函数库lodash三、递归实现深拷贝基础递归升级版递归---解决环引用爆栈问题最终版递归---解决其余类型拷贝结果 一、通过JSON.stringify JSON.parse(JSON.stringify(obj))是比较常用的深拷贝方法之一 原理:利用JSON.stringify 将JavaScript对象序列化成为JSO

iOS剪贴板同步到Windows剪贴板(无需安装软件的方案)

摘要 剪贴板同步能够提高很多的效率,免去复制、发送、复制、粘贴的步骤,只需要在手机上复制,就可以直接在电脑上 ctrl+v 粘贴,这方面在 Apple 设备中是做的非常好的,Apple 设备之间的剪贴板同步功能(Universal Clipboard)确实非常方便,它可以在 iPhone、iPad 和 Mac 之间无缝传输剪贴板内容,从而大大提高工作效率。 但是,iPhone 如何和 Wind

HDD 顺序和随机文件拷贝和存储优化策略

对于机械硬盘(HDD),顺序拷贝和随机拷贝涉及到磁头的移动方式和数据的读取/写入模式。理解这些概念对于优化硬盘性能和管理文件操作非常重要。 1. 顺序拷贝 定义: 顺序拷贝指的是数据从硬盘的一个位置到另一个位置按顺序连续读取和写入。这意味着数据在硬盘上的位置是线性的,没有跳跃或回溯。 特点: 磁头移动最小化:由于数据是连续的,磁头在读取或写入数据时只需要在磁盘的一个方向上移动,减少了寻道时

iOS项目发布提交出现invalid code signing entitlements错误。

1、进入开发者账号,选择App IDs,找到自己项目对应的AppId,点击进去编辑, 2、看下错误提示出现  --Specifically, value "CVYZ6723728.*" for key "com.apple.developer.ubiquity-container-identifiers" in XX is not supported.-- 这样的错误提示 将ubiquity