【iOS】OC高级编程 iOS多线程与内存管理阅读笔记——自动引用计数
文章目录
什么是自动引用计数
内存管理/引用计数
概要
内存管理的思考方式
自己生成的对象,自己所持有
非自己生成的对象,自己也能持有
不再需要自己持有的对象时释放
无法释放非自己持有的对象
什么是自动引用计数
自动引用计数(ARC,Automatic Reference Counting)是指内存管理中对引用采取自动计数的技术。用苹果官方说明的话说:
在OC中采用ARC机制,让编译器来进行内存管理,在新一代Apple LLVM编译器中设置ARC为有效状态,就无需再键入retain或者release代码。
也就是说,只要满足以下条件,就无需手动输入retain和release代码了:
-
使用Xcode4.2或以上版本
-
使用LLVM编译器3.0或以上版本
-
编译器选项中设置ARC为有效
在以上条件下编译源代码时,编译器将自动进行内存管理。接下来我们先了解一下在ARC之前,程序员是如何手动进行内存管理的
内存管理/引用计数
概要
OC中的内存管理,也就是引用计数,可以用开关房间的灯为例来说明引用计数的机制。
假设办公室里只有一个照明设备,上班进入办公室的人需要照明,所以把灯打开。而对于下班离开的人来说,已经不需要照明了,所以要把灯关掉。但是,并不是每个人都需要进行开关灯的操作的,只要第一个人开了灯,后面的人就不必再开灯了,关灯也必须是最后一个离开的人关灯。所以为了判断办公室里还有多少人,我们就引入一个计数来统计需要照明的人数。
(1)第一个人进来,人数加一,计数从零变成一,因此要开灯
(2)之后每进来一个人,人数就加一
(3)每当有人下班离开,人数就减一
(4)最后一个人离开时,人数减一,计数从一变成零,因此要关灯
在OC中,“对象”就相当于照明设备,“对象的使用环境”就相当于上班进入办公室的人。上班时发出的动作与OC中的对应关系如下表:
OC的内存管理就是基于这个逻辑实现的

内存管理的思考方式
有关于引用计数,正确的思考方式有四条准则:
-
自己生成的对象,自己所持有
-
非自己生成的对象,自己也能持有
-
不再需要自己持有的对象时释放
-
非自己持有的对象无法释放
这就是引用计数式内存管理的思考方式,而在OC的内存管理中,除了“生成”、“持有”、“释放”三个词以外,还要加上“废弃”,这四个词组成了OC内存管理的基本操作
相对应的方法如下表所示:
这些有关内存管理的方法,包含在Cocoa框架中用于OS X、iOS应用开发。Cocoa框架中Foundation框架类库的NSObject类担负内存管理的职责。OC内存管理中的alloc/retain/release/dealoc方法分别指代NSObject类的alloc类方法、retain实例方法、release示例方法和dealloc实例方法
接下来我们详细了解内存管理的思考方式中的各个项目
自己生成的对象,自己所持有
使用以下名称开头的方法名意味着自己生成的对象只有自己持有:
-
alloc
-
new
-
copy
-
mutableCopy
下面写出自己生成并持有对象的源代码,为生成并持有对象,我们使用alloc方法。
// 自己生成并持有对象
id obj = [[NSobject alloc] init];
使用NSObject的类方法就能自己生成并持有对象,指向生成并持有对象的指针被赋给变量obj。另外,使用new类方法也能生成并持有对象。
copy方法基于NSCopying方法约定,由各类实现的copyWithZone:方法生成并持有对象的副本,mutableCopy也一样,二者区别只在于生成的对象是否可变。这些方法生成的对象,虽然是对象的副本,但也属于“自己生成并持有对象”。
此外,根据上述“使用以下名称开头的方法名”,下列名称也意味着自己生成并持有对象
-
allocMyObject
-
newThatObject
-
copyThis
-
mutableCopyYourObject
但以下名称,并不属于同一类别的方法
-
allocate
-
newer
-
copying
-
mutableCopyed
非自己生成的对象,自己也能持有
用上述项目之外的方法(即alloc/new/copy/mutableCopy以外的方法)取得的对象,因为非自己生成并持有,所以自己不是该对象的持有者。
//取得非自己生成并持有的对象
id obj = [NSMutableArray array];
//取得的对象存在,但自己不持有对象
这段代码中,NSMutableArray类对象被赋给变量obj,但变量obj自己并不持有该对象,使用retain方法可以持有对象
//取得非自己生成并持有的对象
id obj = [NSMutableArray array];
//取得的对象存在,但自己不持有对象
[obj retain];
//自己持有对象
通过retain方法,可以将对象变为自己所持有的
不再需要自己持有的对象时释放
自己持有的对象,一旦不再需要时,持有者有义务释放该对象,使用release方法
id obj = [[NSObject alloc] init];
[obj release];
//释放对象
指向对象的指针仍然被保留在变量obj中,貌似能够访问
但对象一经释放绝对不可访问
这样,对象就被release方法释放了,自己生成而非自己持有的对象,如果用retain变成自己持有,同样可以用release释放
用alloc/new/copy/mutableCopy方法生成并持有的对象,或者用retain方法持有的对象,一旦不再需要,务必用release释放。
如果要用某个方法生成对象,并将其返还给该方法调用方,源代码如下:
- (id)allocObject {id obj = [[NSObject alloc] init];return obj;
}
如上例,将用alloc方法生成的对象直接返回。就能让调用方也持有该对象。
注意,这里与上文命名规则相符合,使用allocObject也就意味着“自己生成并持有对象”
那像[NSMutableArray array]这种方法使取得的对象存在,但自己不持有对象,又是如何实现的呢?根据上文规则,不能使用alloc/new/copy/mutableCopy开头的方法名,因此我们使用object这个方法名
- (id)object {
id obj = [[NSObject alloc] init];
[obj autorelease];
//取得对象存在,但自己不持有对象
return obj;
}
上例中,我们使用了autorelease方法,用这个方法可以使取得的对象存在,但自己不持有对象,autorelease提供这种功能,是对象在超出指定生存范围时能自动并正确的释放。

使用NSMutableArray类的array类方法可以取得谁都不持有的对象,这些方法都是通过autorelease来实现的。
无法释放非自己持有的对象
得到非自己持有的对象无法释放,倘若在应用程序中释放了非自己持有的对象就会造成崩溃。例如自己生成并持有对象后,在释放完不再需要的对象之后再次释放
id obj = [[NSObject alloc] init];
[obj release];
[obj release];
//应用程序崩溃!
//访问已经废弃的对象时崩溃
或者“取得的对象存在,但自己不持有对象”时释放
id obj1 = [obj0 object];
//取得对象存在,但自己不持有
[obj1 release];
//程序崩溃
以上就是“引用计数式内存管理”的思考方式
相关文章:
【iOS】OC高级编程 iOS多线程与内存管理阅读笔记——自动引用计数
文章目录 什么是自动引用计数 内存管理/引用计数 概要 内存管理的思考方式 自己生成的对象,自己所持有 非自己生成的对象,自己也能持有 不再需要自己持有的对象时释放 无法释放非自己持有的对象 什么是自动引用计数 自动引用计数(AR…...
网络安全-LD_PRELOAD,请求劫持
目录 一、环境 二、开始做题 三、总结原理 四、如何防护 一、环境 我们这里用蚁剑自带的靶场第一关来解释 docker制作一下即可 二、开始做题 首先环境内很明显给我们已经写好了webshell 同样我们也可以访问到 我们使用这个蚁剑把这个webshell连上 我们发现命令不能执行&am…...
GO入门之值传递于引用(指针、内存地址)传递扫盲
GO入门之值传递于引用(指针、内存地址)传递扫盲 Go 语言中,值传递和引用(指针)传递是两个关键的概念。通过案例可以很好地展示两者的区别。 值传递与引用传递的区别: 值传递:传递的是变量的副…...
【渗透测试】-vulnhub源码框架漏洞-Os-hackNos-1
vulnhub源码框架漏洞中的CVE-2018-7600-Drupal 7.57 文章目录 前言 1.靶场搭建: 2.信息搜集: 主机探测: 端口扫描: 目录扫描: 3.分析: 4.步骤: 1.下载CVE-2018-7600的exp 2.执行exp: 3.写入木…...
sqli-lab靶场学习(三)——Less8-10(盲注、时间盲注)
Less8 第八关依然是先看一般状态 http://localhost/sqli-labs/Less-8/?id1 然后用单引号闭合: http://localhost/sqli-labs/Less-8/?id1 这关的问题在于报错是不显示,那没办法通过上篇文章的updatexml大法处理。对于这种情况,需要用“盲…...
Pybullet 安装过程
Pybullet 安装过程(windows) 1. 安装C编译工具2. 安装Pybullet 1. 安装C编译工具 pybullet 需要C编译套件,直接装之前检查下,要不会报缺少某版本MVSC的error,最好的方式是直接下载visual studio,直接按默认…...
Error when custom data is added to Azure OpenAI Service Deployment
题意:在向 Azure OpenAI 服务部署添加自定义数据时出现错误。 问题背景: I receive the following error when adding my custom data which is a .txt file (it doesnt matter whether I add it via Azure Cognitive Search, Azure Blob Storage, or F…...
libreoffice word转pdf
一、准备一个word文件 运行: cd /root libreoffice --headless --convert-to pdf --outdir /root/output doc1.docx 发现中文乱码: 此时我们需要给linux 上添加中文字体: centos7 添加中文字体 再次运行正常: libreoffice --h…...
java -----泛型
泛型的理解和好处 泛型是在JDK5之后引入的一个新特性,可以在编译阶段约束操作的数据类型,并进行检查。 泛型的格式为 <数据类型> import java.util.ArrayList;SuppressWarnings({"all"}) public class Generic02 {public static void…...
Springboot 文件上传下载相关问题
文章目录 关于Springboot 文件上传下载问题解决方案注意事项文件上传文件下载文件删除文件在线打开在写练习的时候,发现了一些小小的问题,已经在 上述代码中体现。① 代码路径碰到中文的时候,会有乱码,需要转换(内容中…...
【Kotlin 与 Java 互操作】Java中调用带有默认值的Kotlin函数(十四)
导读大纲 1.0.1 Java 没有默认参数值的概念1.0.2 使用 JvmOverloads 来简化调用 1.0.1 Java 没有默认参数值的概念 因此当从 Java 调用带有默认参数值的 Kotlin 函数时 1. 必须明确指定所有参数值 fun <T> joinToString(collection: Collection<T>,separator: St…...
点赞系统实现
点赞功能是社交、电商等几乎所有的互联网项目中都广泛使用。虽然看起来简单,不过蕴含的技术方案和手段还是比较多的。 下面将分享之前做的判题OJ系统的点赞系统的思路。 1.需求分析 点赞功能与其它功能不同,没有复杂的原型和需求,仅仅是一…...
c++进阶学习-----继承
1.继承的概念及定义 1.1继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。 继承呈现了面向对象 程序设计的…...
C++学习笔记(37)
302、makefile 在实际开发中,项目的源代码文件比较多,按类型、功能、模块分别存放在不同的目录和文件中,哪 些文件需要先编译,那些文件后编译,那些文件需要重新编译,还有更多更复杂的操作。 make 是一个强大…...
Redis发布和订阅
Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者(sub) 接收消息 可以实现进程间的消息传递。这种模式非常适用于实时消息传递、事件通知和消息分发等场景 Redis可以实现消息中间件MQ的功能,通过发布订阅实现消息…...
计算机毕设设计推荐-基于python+Djanog大数据的电影数据可视化分析
精彩专栏推荐订阅:在下方主页👇🏻👇🏻👇🏻👇🏻 💖🔥作者主页:计算机毕设木哥🔥 💖 文章目录 一、电影数据可视…...
dhtmlxGantt 甘特图 一行展示多条任务类型
效果如图: 后台拿到数据 处理之后如图: 含义: 如上图所示, 如果一行需要展示多个 需要给父数据的那条添加render:split属性, 子数据的parent为父数据的Id即可 切记 父数据的id 别为0 为0 时 会出现错乱 因为有些小伙伴提出分段展示的数据结构还是有点问题,下面展示一个完整…...
COLORmap
在这段MATLAB代码中,surf(peaks)、map的定义以及colormap(map)的调用共同完成了以下任务: 1. **绘制曲面图**: - surf(peaks):这个函数调用了MATLAB内置的peaks函数来生成数据,并使用surf函数将这些数据绘制成一个…...
手机在网状态查询接口如何用Java进行调用?
一、什么是手机在网状态查询接口? 手机在网状态查询接口,又叫运营商在网状态查询,手机号在网状态查询,传入手机号码,查询该手机号的在网状态,返回内容有正常使用、停机、在网但不可用、不在网(…...
mysql性能优化- 数据库配置优化
MySQL 性能优化 - 数据库配置优化 MySQL 是一个广泛使用的关系型数据库管理系统,但随着数据量的增长和访问频率的提高,其性能可能会成为瓶颈。为了保持高效的性能,除了应用层的查询优化和索引优化之外,数据库配置优化 也是非常重…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...
git删除本地分支和远程分支
删除本地分支 git branch -d 分支名删除远程分支 git push origin --delete 分支名...
