0
点赞
收藏
分享

微信扫一扫

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

在本章中,你将学会ARC自动引用计数机制的使用方法。

前言

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

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

如有错误,以你为准。

项目创建

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

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

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("调用析构函数")
}
}

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

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

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

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

强引用

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

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

Swift实用小册23: ARC自动引用计数机制的使用_构造函数_03

上述代码中,我们创建了一个​​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("释放") }
}

Swift实用小册23: ARC自动引用计数机制的使用_构造函数_04

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

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

var model1: Model1?
var model2: Model2?

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

model1 = nil

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

如果这时候,我们将​​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

以上就是本章的全部内容。

快来动手试试吧!

如果本专栏对你有帮助,不妨点赞、评论、关注~

举报

相关推荐

0 条评论