浅谈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 : String
    var name1 : String
    
    
    init(name0: String, name1: String) {
        self.name0 = name0
        self.name1 = name1
    }
    
    deinit {
        print("Person is deallocated")
    }
}


let person : Person? = Person(name0: "whj", name1: "whj1")

var man = person
var women = person

man = 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 : String
    var name1 : String
    var band : Band?
    
    init(name0: String, name1: String) {
        self.name0 = name0
        self.name1 = name1
    }
    
    deinit {
        print("Person is deallocated")
    }
}

class Band{
    var bandName : String
    var 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 = person

person = nil
band = nil

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

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

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

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

3.弱引用weak

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

        将代码改成:



//简单类Person
class Person{
    
    var name0 : String
    var name1 : String
    weak var band : Band?
    
    init(name0: String, name1: String) {
        self.name0 = name0
        self.name1 = name1
    }
    
    deinit {
        print("Person is deallocated")
    }
}

class Band{
    var bandName : String
    var 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 = person

person = nil
band = nil

4.无主引用Unowned

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

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

5.Autoreleasepool 自动释放池

在Swift中,自动释放池(Autorelease Pool)是一种用于管理内存释放的机制,它可以减少内存峰值并提高内存使用效率。自动释放池允许您暂时保留对象,直到您离开当前代码块,然后自动释放它们。

在Swift中,您可以使用 autoreleasepool 块来创建自动释放池。在 autoreleasepool 块中创建的对象都会被加入到自动释放池中。当程序离开该块时,自动释放池将被清空,并释放其中的所有对象。

func myFunc() {
    autoreleasepool {
        // 创建一些临时对象
        let obj1 = MyClass()
        let obj2 = MyClass()

        // 在此使用 obj1 和 obj2

    } // 自动释放池在这里被清空
}

        当代码中临时对象较多的时,或者代码执行时间长,那么使用autoreleasepool可以对项目的内存利用效率产生积极的影响

参考:

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/510923.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

EFPN代码解读

论文 Extended Feature Pyramid Network for Small Object Detection python3 D:/Project/EFPN-detectron2-master/tools/train_net.py --config-file configs/InstanceSegmentation/pointrend_rcnn_R_50_FPN_1x_coco.yaml --num-gpus 1 训练脚本 cfg 中的配置 先获取配置…

JavaWeb 项目运行配置

JavaWeb 项目运行配置

保持ssh断开后,程序不会停止执行

保持ssh断开后,程序不会停止执行 一、前言 笔者做远程部署搞了一阵子,快结项时发现一旦我关闭了ssh连接窗口,远程服务器会自动杀掉我在ssh连接状态下运行的程序。 这怎么行,岂不是想要它一直运行还得要一台电脑一直打开ssh连接咯…

【优选算法专栏】专题十六:BFS解决最短路问题---前言

本专栏内容为:算法学习专栏,分为优选算法专栏,贪心算法专栏,动态规划专栏以及递归,搜索与回溯算法专栏四部分。 通过本专栏的深入学习,你可以了解并掌握算法。 💓博主csdn个人主页:小…

【QingHub】企业级应用开发管理

QingHub 企业级应用开发设计器是QingHub Studio的一个核心模块,它可以实现应用搭建、团队管理,共享开发,可以快速接入API接口,复杂功能可以通过自定义脚本快速实现业务逻辑。打通前端开发与后台业务逻辑一体化。通过可视化的方式&…

使用 PDManer 对数据库表建模(建表语句生成,代码生成)

目录 前言 基本使用教程 新建项目 创建表 关系图 建表语句 生成代码 导入 前言 在软件开发中过程中,一般分为几个过程:需求分析、概要设计、详细设计、编码实现、软件测试和软件交付。 在概要设计和详细设计过程中,则需要对业务进…

苍穹外卖06(HttpClient,微信小程序开发,微信登录流程,获取授权码从微信平台获取用户信息)

目录 一、HttpClient 1. 介绍 2. 入门案例 1 导入依赖(已有) 2 GET方式请求 2 POST方式请求 二、微信小程序开发 1. 介绍 2. 准备工作 1 注册小程序获取AppID 注册小程序 完善小程序信息 2 下载并安装开发者工具 3 设置小程序开发者工具(必做) 3. 入门案例 1 小…

CentOS 7 下离线安装RabbitMQ教程

CentOS 7 下安装RabbitMQ教程一、做准备(VMWare 虚拟机上的 CentOS 7 镜像 上安装的) (1)准备RabbitMQ的安装包(rabbitmq-server-3.8.5-1.el7.noarch)下载地址mq https://github.com/rabbitmq/rabbitmq-se…

基于51单片机的简易计算器设计

1、任务 本课题模拟计算器设计硬件电路采用三部分电路模块构成, 第一部分是键盘模块电路,采用4*4矩阵式键盘作为输入电路; 第二部分是LCD1602液晶显示模块; 第三部分是以51单片机作为控制核心。 软件程序主要由三部分组成&am…

AWS-EKS 给其他IAM赋予集群管理权限

AWS EKS 设计了权限管理系统,A用户创建的集群 B用户是看不到并且不能管理和使用kubectl的,所以我们需要共同管理集群时就需要操场共享集群访问给其他IAM用户。 两种方式添加集群控制权限(前提:使用有管理权限的用户操作&#xff…

子集与全排列问题(力扣78,90,46,47)

系列文章目录 子集和全排列问题与下面的组合都是属于回溯方法里的,相信结合前两期,再看这篇笔记,更有助于大家对本系列的理解 一、组合回溯问题 二、组合总和问题 文章目录 系列文章目录题目子集一、思路二、解题方法三、Code 子集II一、思…

基于SSM的网上打印管理

摘要 进入二十一世纪以来,计算机技术蓬勃发展,人们的生活发生了许多变化。很多时候人们不需要亲力亲为的做一些事情,通过网络即可完成以往需要花费很多时间的操作,这可以提升人们的生活质量。计算机技术对人们生活的改变不仅仅包…

不会还有程序员不知道这几个宝藏学习平台吧?还不来码住!

咱作为程序员可谓是赶上了发展的时代啊!前有ChatGPT,后有5G、物联网等等层出不穷。这正是咱大展身手、大赚一笔的好时候啊!有多少人趁着风口期大干一笔,狠狠投入,最终不说是top级别,也至少是羡煞众人啊&…

最新AI智能系统ChatGPT网站源码V6.3版本,GPTs、AI绘画、AI换脸、垫图混图+(SparkAi系统搭建部署教程文档)

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,那么如何搭建部署AI创作ChatGPT?小编这里写一个详细图文教程吧。已支持GPT…

[从0开始AIGC][Transformer相关]:Transformer中的激活函数:Relu、GELU、GLU、Swish

[从0开始AIGC][Transformer相关]:Transformer中的激活函数 文章目录 [从0开始AIGC][Transformer相关]:Transformer中的激活函数1. FFN 块 计算公式?2. GeLU 计算公式?3. Swish 计算公式?4. 使用 GLU 线性门控单元的 FF…

Redis基本配置及安装

Redis也叫Remote dictionary server,是一个开源的基于内存的数据存储系统。它可以用作数据库、缓存和消息队列等各种场景。它也是目前最热门的NoSQL数据库之一 以下是NoSQL的定义 随着互联网的快速发展,应用系统的访问量越来越大,数据库的性能瓶颈越来越…

自动驾驶中基于Transformer的传感器融合:研究综述

自动驾驶中基于Transformer的传感器融合:研究综述 论文链接:https://arxiv.org/pdf/2302.11481.pdf 调研链接:https://github.com/ApoorvRoboticist/Transformers-Sensor-Fusion 附赠自动驾驶学习资料和量产经验:链接 摘要 本…

解密JavaScript混淆:剖析JScrambler、JSFack、JShaman等五款常用加密工具

摘要 本篇技术博客将介绍五款常用且好用的在线JavaScript加密混淆工具,包括 jscrambler、JShaman、jsfack、freejsobfuscator 和 jjencode。通过对这些工具的功能及使用方法进行详细解析,帮助开发人员更好地保护和加密其 JavaScript 代码,提…

图的应用试题

01.任何一个无向连通图的最小生成树( )。 A.有一棵或多棵 B.只有一棵 C.一定有多棵 D.可能不存在 02.用Prim算法和Kruskal算法构造图的最小生成树,…

食物链(并查集) 维护权值写法,非常详细,适合新手服用

题目描述: 动物王国中有三类动物 A,B,C这三类动物的食物链构成了有趣的环形。 A 吃 B,B 吃 C,C吃 A。 现有 N 个动物,以 1∼N 编号。 每个动物都是 A,B,C 中的一种,但是我们并不知道它到底是哪一种。 有人用两种说法对…