Swift实用小册23: ARC自动引用计数机制的使用

举报
文如秋雨 发表于 2022/08/30 13:23:10 2022/08/30
【摘要】 在本章中,你将学会ARC自动引用计数机制的使用方法。前言和Apple官网或者网上分享的教程类文章不同,我将以实际开发角度讲述Swift语言的一些概念和用法,方便大家更好地学习和掌握Swift语言。这同时也是对自己学习Swift语言过程的知识整理。如有错误,以你为准。项目创建我们新建一个PlayGround项目,命名为SwiftARC。ARC的定义ARC,自动引用计数机制,是Swift官方提供...
在本章中,你将学会ARC自动引用计数机制的使用方法。

前言


和Apple官网或者网上分享的教程类文章不同,我将以实际开发角度讲述Swift语言的一些概念和用法,方便大家更好地学习和掌握Swift语言。

这同时也是对自己学习Swift语言过程的知识整理。

如有错误,以你为准。

项目创建


我们新建一个PlayGround项目,命名为SwiftARC




ARC的定义


ARC,自动引用计数机制,是Swift官方提供的一种跟踪和管理应用程序的内存的机制。

ARC可以帮助我们设计的应用程序自动释放内存,保证我们实例在使用完成后不会占用内存资源,保障应用程序运行的流畅性。

ARC的功能


使用 init() 方法创建一个类的实例时,ARC 会分配内存用来储存实例的信息,内存中会包含实例的类型信息,以及这个实例所有相关属性的值。

当实例不再被使用时,ARC 释放实例所占用的内存。为了确保使用中的实例不会被销毁,ARC 会跟踪和计算每一个实例正在被多少属性,常量和变量所引用。

实例赋值给属性、常量或变量,都会创建实例的强引用,只要强引用还在,实例就不会被销毁。

ARC的使用


我们用之前Destructor析构函数的例子展示ARC自动引用计数机制的使用。示例:

class appInformation {
    var appName: String
    var appVersion: String
    var appAuthor: String

    // 构造函数
    init(appName: String, appVersion: String, appAuthor: String) {
        self.appName = appName
        self.appVersion = appVersion
        self.appAuthor = appAuthor
        print("调用构造函数")
    }

    // 析构函数
    deinit {
        print("调用析构函数")
    }
}




上述代码中,我们定义了一个appInformation类,然后声明了三个String类型的变量:appName、appVersion、appAuthor。

appInformation类有一个构造器,构造器给实例的变量属性赋值,然后打印一条信息:调用构造函数

appInformation类有一个析构器,析构器在实例被销毁时打印一条信息:调用析构函数

强引用


接下来,我们创建一个实例。

var app: appInformation?
app = appInformation(appName: "Swift实用小册", appVersion: "1.0.0", appAuthor: "文如秋雨”)
app = nil


上述代码中,我们创建了一个appInformation类的实例:app,并将appInformation实例赋值给了app。

这样在我们调用appInformation构造器时,会打印输出一条信息:调用构造函数。

由于appInformation实例赋值给了app变量,因此app变量和appInformation实例之间会建立一个强引用。

又由于这个强引用的存在,ARC自动引用计数机制会保证appInformation实例会保存在内存中不会被销毁。

当我们要断开强引用时,我们可以通过给app变量赋值nil,这样这个强引用就会被断开,appInformation实例也就会被销毁,从而释放内存。

弱引用


在上面的例子中,ARC会跟踪我们创建的appInformation实例的引用数量,并且在不需要用到的时候销毁它。

但如果我们使用2个或以上的类的实例,然后它们之间互相建立强引用,这就导致永远都不可能释放这部分的内存,这是一个很严重的问题。

因此,我们引用了弱引用的概念。

弱引用能保证我们在多个实例循环引用时不保持强引用的状态。示例:

class Model1 {
    let name: String
    init(name: String) { self.name = name }
    var strongModel: Model2?
    deinit { print("释放") }
}

class Model2 {
    let title: String
    init(title: String) { self.title = title }
    weak var weakModel: Model1?
    deinit { print("释放") }
}



上述代码中,我们创建了2个类:Model1、Model2,并都对其进行初始化。

然后在Model1类中强引用Model2类,在Model2类中弱引用Model1类,然后我们建立两个变量model1、model2之间的强引用,并关联两个实例:

var model1: Model1?
var model2: Model2?
model1 = Model1(name: "文如秋雨")
model2 = Model2(title: "Swift实用小册”)

model1 = nil




如果这时候,我们将model1的强引用断开,那么类Model1的实例就会被销毁,又由于我们Model2使用弱引用,这时候就不会循环创建两个类的实例的强引用关系,导致两个实例都占用内存。

本章代码


import UIKit
class appInformation {
    var appName: String
    var appVersion: String
    var appAuthor: String
    // 构造函数
    init(appName: String, appVersion: String, appAuthor: String) {
        self.appName = appName
        self.appVersion = appVersion
        self.appAuthor = appAuthor
        print("调用构造函数")
    }
    // 析构函数
    deinit {
        print("调用析构函数")
    }
}
var app: appInformation?
app = appInformation(appName: "Swift实用小册", appVersion: "1.0.0", appAuthor: "文如秋雨")
app = nil
class Model1 {
    let name: String
    init(name: String) { self.name = name }
    var strongModel: Model2?
    deinit { print("释放") }
}
class Model2 {
    let title: String
    init(title: String) { self.title = title }
    weak var weakModel: Model1?
    deinit { print("释放") }
}
var model1: Model1?
var model2: Model2?
model1 = Model1(name: "文如秋雨")
model2 = Model2(title: "Swift实用小册")
model1 = nil



以上就是本章的全部内容。
快来动手试试吧!
如果本专栏对你有帮助,不妨点赞、评论、关注~
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。