【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 是一个广泛使用的关系型数据库管理系统,但随着数据量的增长和访问频率的提高,其性能可能会成为瓶颈。为了保持高效的性能,除了应用层的查询优化和索引优化之外,数据库配置优化 也是非常重…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...

TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

宇树科技,改名了!
提到国内具身智能和机器人领域的代表企业,那宇树科技(Unitree)必须名列其榜。 最近,宇树科技的一项新变动消息在业界引发了不少关注和讨论,即: 宇树向其合作伙伴发布了一封公司名称变更函称,因…...