当前位置: 首页 > news >正文

浅谈iOS开发中的自动引用计数ARC

1.ARC是什么

      我们知道,在C语言中,创建对象时必须手动分配和释放适量的内存。然而,在 Swift 中,当不再需要类实例时,ARC 会自动释放这些实例的内存

      Swift 使用 ARC 来跟踪和管理应用程序的内存,其主要是由Objective-C语言提供的。ARC是一种自动化的内存管理机制,它通过在编译时插入内存管理代码来自动管理对象的引用计数。ARC机制可以让开发者不用手动管理对象的引用计数,从而减少了内存泄漏和野指针等问题的发生。

      总的来说:

  1. Swift中每个对象都有一个【被引用计数】;
  2. 当对象A被引用时(实例),对象A的被引用计数会 + 1;
  3. 当对象A被放弃引用时,对象A的被引用计数会 - 1;
  4. 只有当对象A的被引用计数为 0 的时候,ARC才会释放对象A的内存。

2.强引用stong

      为了防止实例在仍然需要时被释放,属性、常量或变量在分配实例时会建立对实例的强引用。


//简单类Person
class Person{var name0 : Stringvar name1 : Stringinit(name0: String, name1: String) {self.name0 = name0self.name1 = name1}deinit {print("Person is deallocated")}
}let person : Person? = Person(name0: "whj", name1: "whj1")var man = person
var women = personman = nil
women = nil

        以上设置了一个简单类Person,它有两个属性:init()deinit()deinit()方法仅在释放时才会被调用。类定义之后, Person类的实例已初始化。还有另外两个变量(man、women)指向与第一个变量(person)相同的实例。

        当我们将man和women设置为nil时,发现deinit()并没有发挥作用,说明该实例并没有被释放内存,这是因为三个变量(person、man、women)都对该实例有着很强的引用,当三个变量均引用该实例的时候, 该实例的ARC的计数为3。因此,即使将两个变量设置为 nil,引用计数仍然为 1。除非引用计数不为零,否则实例仍然存在。

循环引用(类之间强引用引起)

        循环引用可以简单的理解为A引用了B,B也引用了A,因为两者相互持有,所以ARC无法释放两者,这在应用程序中是致命的。

//简单类Person
class Person{var name0 : Stringvar name1 : Stringvar band : Band?init(name0: String, name1: String) {self.name0 = name0self.name1 = name1}deinit {print("Person is deallocated")}
}class Band{var bandName : Stringvar person : Person?init(bandName: String) {self.bandName = bandName}deinit {print("\(bandName) is deallocated.")}}var person : Person? = Person(name0: "whj", name1: "whj1")
var band : Band? = Band(bandName: "ruishi")person?.band = band
band?.person = personperson = nil
band = nil

        在上面的示例中,有两个简单的类,称为PersonBand。每个类都有一个可选属性,该属性具有另一个类的类型。正如您在代码中看到的,这些属性在初始化后被分配给彼此的实例。目前两者的关系可以如下图描述:

        当我们设置person和band为nil ,关系如下:

        由于变量被设置为nil,变量和实例之间的强引用消失了。然而,实例仍然存在,因为“ Band”属性和“Person”属性对每个实例都有很强的引用。只要存在强引用,引用计数就不会为零。因此,即使变量为零,实例也不会被释放。这称为循环引用。这会导致ARC 无法释放其内存,造成内存泄漏。

        Block 和 代理 、NSTimer均有可能造成循环引用。

3.弱引用weak

        解决循环引用的方法之一就是使用弱引用weak。弱引用weak对实例没有强引用。换句话说,它不会增加实例的强引用计数。因此,如果使用weak关键字,它并不真正参与实例的生命周期管理。

        将代码改成:

//简单类Person
class Person{var name0 : Stringvar name1 : Stringweak var band : Band?init(name0: String, name1: String) {self.name0 = name0self.name1 = name1}deinit {print("Person is deallocated")}
}class Band{var bandName : Stringvar person : Person?init(bandName: String) {self.bandName = bandName}deinit {print("\(bandName) is deallocated.")}}var person : Person? = Person(name0: "whj", name1: "whj1")
var band : Band? = Band(bandName: "ruishi")person?.band = band
band?.person = personperson = nil
band = nil

 

4.无主引用Unowned

        解决循环引用的另一种方法就是使用无主引用Unowned。与弱引用相同,无主引用不会增加引用计数。那么,无主引用Unowned和弱引用weak有什么区别呢?区别在于:

weak是可选类型,可以设置为nil,而Unowned是值类型,其必须持有具体的值。

参考:

https://kentakodashima.medium.com/ios-arc-memory-management-in-ios-30aae3da92cf

iOS内存管理_ios 内存管理-CSDN博客

相关文章:

  • 使用llamafile 构建本地大模型运用
  • spring boot的返回值里面含有net.sf.json.JSONObject 报错net.sf.json.JSONNull[“empty“])]
  • <深度学习入门学习笔记P1>——《深度学习》
  • 后端返回文件流pdf 下载
  • 【AIGC调研系列】Starling-LM-7B模型与其他模型相比的优势和劣势
  • 更高效稳定 | 基于ACM32 MCU的编程直流电源应用方案
  • C#WPF控件TextBlock详解
  • 通俗易懂:如何通过JVM参数来调整内存大小?
  • OpenFeign原理整理【Java面试】
  • Gitlab CI---could not read username for xxx: no such device or address
  • flutter 打包成web应用后怎么通过url跳转页面
  • Chrome 插件 tabs API 解析
  • uniApp使用XR-Frame创建3D场景(8)粒子系统
  • 目标检测+车道线识别+追踪
  • pulsar: kafka on pulsar之把pulsar当kafka用
  • 【译】JS基础算法脚本:字符串结尾
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • Effective Java 笔记(一)
  • Java 网络编程(2):UDP 的使用
  • laravel with 查询列表限制条数
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • Ruby 2.x 源代码分析:扩展 概述
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • 基于OpenResty的Lua Web框架lor0.0.2预览版发布
  • 技术发展面试
  • 人脸识别最新开发经验demo
  • 软件开发学习的5大技巧,你知道吗?
  • 设计模式走一遍---观察者模式
  • 使用 Docker 部署 Spring Boot项目
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • ​你们这样子,耽误我的工作进度怎么办?
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • ​软考-高级-系统架构设计师教程(清华第2版)【第12章 信息系统架构设计理论与实践(P420~465)-思维导图】​
  • #define用法
  • (14)目标检测_SSD训练代码基于pytorch搭建代码
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (推荐)叮当——中文语音对话机器人
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .a文件和.so文件
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .NET C#版本和.NET版本以及VS版本的对应关系
  • .NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions
  • .NET Framework Client Profile - a Subset of the .NET Framework Redistribution
  • .net 按比例显示图片的缩略图
  • .NET/C# 检测电脑上安装的 .NET Framework 的版本
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • @ComponentScan比较
  • @Mapper作用
  • @Query中countQuery的介绍
  • [C++]STL之map
  • [CareerCup][Google Interview] 实现一个具有get_min的Queue
  • [dfs搜索寻找矩阵中最长递减序列]魔法森林的秘密路径