探索Objective-C中的对象复制:深入理解copy和mutableCopy

NSString为什么copy修饰?深拷贝和浅拷贝的区别?NSMutableArray进行copy是深拷贝还是浅拷贝?NSMutablearray里的内容如果是NSString,那么mutablecopy的话是拷贝的内容还是内容地址都拷贝?NSArray的内容是OC对象还是其他的对象,是否可以是非OC对象?nsarray存储的是内容还是地址?下面针对上面的问题一一分析。

首先,让我们引用阳神Sunny博客中的一道面试题作为引子:

这个问题揭示了深入了解copy的重要性。那么,copy究竟是什么,它又有何用途呢?接下来,我们将一起探索copy的奥秘。

  1. Copy和mutableCopy方法

在Objective-C中,copy和mutableCopy是对象特有的方法,它们在NSObject类及其子类中都有定义。此外,还存在对应的类方法copyWithZone:,其参数为一个结构体指针,用于指定内存区域。同时,为了支持这些方法,NSCopying和NSMutableCopying两个协议也被引入。

1.1 ◆ copy方法定义与特性和类方法的区别

首先,我们来看copy和mutableCopy在Objective-C中的重要性。其中,+copy:和+copyWithZone:这两个方法,主要是为了确保"类"对象也能遵循NSCopying协议,从而能够作为键值对插入NSDictionary中。由于类对象在全局范围内只能存在一份,因此这两个方法实际上只是简单地返回self。值得注意的是,这两个方法在ARC(自动引用计数)环境下是不可用的。

另一方面,-copy和-mutableCopy这两个方法在调用时,会创建一个新的副本对象,并直接返回-copyWithZone:和-mutableCopyWithZone:方法的结果。

1.2 ◆ copy协议与实现

为了实现这些方法,对象需要遵循特定的协议。常见的NSString、NSArray、NSDictionary等类都已经遵守了这些协议,因此它们可以在需要时生成副本对象。然而,NSObject类本身并未实现-copyWithZone:和-mutableCopyWithZone:这两个方法,因此,若子类对象需要使用-copy和-mutableCopy,则必须实现NSCopying和NSMutableCopying这两个协议。

1.3 ◆ NSZone的历史背景和弃用情况

关于NSZone,它已被Apple弃用,因此我们无需深入探讨。

  1. 拷贝的意义和深浅拷贝解析
2.1 ◆ 拷贝的核心意义

拷贝,字面意思即为拷贝或克隆,其核心目的在于复制出一份与原内容完全一致的新内容。通过拷贝,我们可以实现对原内容的独立操作,从而确保在改变副本时不会影响到原内容,反之亦然。

2.2 ◆ 深拷贝与浅拷贝

接下来,我们通过具体示例来讲解容器和非容器对象的拷贝方式。其中,深拷贝与浅拷贝有以下不同点:

  1. 浅拷贝(或称为指针拷贝):仅复制对象的引用,不会生成新对象。

  2. 深拷贝(或称为对象拷贝):真正创建一个新的对象,并将其原始数据复制进去。

  3. 具体对象的拷贝分析

3.1 ◆ 非容器对象的拷贝分析

首先,我们来看NSString和NSMutableString这两种非容器对象。在处理这两种对象时,拷贝的意义主要体现在对原始对象的保护上。通过拷贝,我们可以获得原始对象的一个独立副本,从而在不影响原始对象的基础上进行各种操作。这种拷贝方式通常被称为浅拷贝。

3.2 ◆ 容器对象的深层拷贝探讨与实现

接下来,我们转向NSArray和NSMutableArray这两种容器对象。与非容器对象不同,容器对象的拷贝涉及到更复杂的操作。为了确保在改变副本时不会影响到原内容,我们需要进行深层次的拷贝。这种深拷贝方式会递归地复制容器对象中的所有元素,从而生成一个与原容器对象完全独立的新容器对象。

我们发现,即使在多次执行copy操作时,容器对象仍会生成新的对象,这是因为必须避免影响原始内容。

3.3 ◆ 容器对象的内存管理和优化

为了实现真正的元素对象拷贝,可以通过归档技术来达成。

  1. 对象复制的总结
4.1 ◆ 浅拷贝与深拷贝的关键点

在对象复制方面,存在浅拷贝与深拷贝的两种方式。理解这两种拷贝方式的关键在于把握其目的:确保原始内容与副本相互独立,互不影响。

4.2 ◆ 内存管理和copy属性的使用

在内存管理上,浅拷贝不会生成新对象,但会进行retain操作以保持其存活。而深拷贝则会创建新对象。此外,使用copy属性而非property的原因也在于此,以确保在修改副本时不会影响原始内容。

  1. 内存管理的区别与总结
5.1 ◆ MRC与ARC中的retain与strong比较

在MRC和ARC环境下,我们分别使用retain和strong来修饰对象。然而,在某些情况下,为了防止对象被意外释放,我们需要通过copy来进行属性设置。

5.2 ◆ 现代开发习惯和建议

尽管在ARC时代,使用strong和copy都能达到类似的效果,但主要还是基于习惯。当然,行业中的一些推荐和经验值得我们参考,例如通过将strong替换为copy来避免潜在的循环引用问题。

5.3 ◆ 远程控制的尝试与思考

今天尝试通过屏幕共享功能来远程控制其他Mac时,也让我思考到用户体验和便捷性的重要性。最终选择QQ的远程功能,因为它简单而高效。这启发我们在功能设计时应注重用户体验,使用户能够更便捷地操作。

相关推荐
1024奇点7 小时前
【仓颉语言入门 · 第二篇 第 22 课】
开发语言·ide·开源
Warren2Lynch8 小时前
C4 模型详解:利用 Visual Paradigm 可视化软件架构的综合指南
开发语言·uml
Knight_AL8 小时前
Java 文件下载时文件名中的 `#` 被转换成 `%23`?一次 URL 编码与解码问题排查
java·开发语言
FRing039 小时前
vue2干货总结2(v-bind、v-for、v-model、指令修饰符、v-bind操作class和style)
开发语言·前端·vue.js·vue2
by209999 小时前
C++ 智能指针的所有权与使用
开发语言·c++·经验分享
砚底藏山河10 小时前
python量化自定义周期 K 线合成
java·开发语言·数据库·python·金融
IT召唤狮10 小时前
开源企业级零信任项目Pangolin,零信任能挡住PHP核弹漏洞吗?
开发语言·开源·php
知已难寻10 小时前
03 · OpenStack的计算管理 Nova
运维·服务器·开发语言·云原生·云计算·openstack·开源软件
Rover Ramble10 小时前
C++ 用互斥锁实现读写锁
开发语言·c++
码流子11 小时前
移动收费怎么做?手持终端+App+收费中心的架构实践
java·开发语言·架构