简介
Swift 使用 Automatic Reference Counting (ARC) 管理应用内存的使用,ARC自动释放那些不在使用的对象,然而在一些场景下ARC需要更多的对象之间的引用信息来管理内存.
ARC 如何工作
每当你创建一个实例instance对象时,ARC分配一块儿内存用来存储instance对象信息包括对象类型,以及属性的值.
此外,当instance对象不在使用的时候,ARC释放instance对象所占的内存,以便释放的内存可在利用.然而,
instance对象被ARC释放后,将不在允许访问该instance对象的属性或者方法,如果你尝试访问,结果就会使APP crash
为了确保正在使用的instance对象,不被释放. ARC追踪分配给instance对象的属性 property 常量 变量 即 引用计数.只要instance对象被引用着,就不会被释放.
ARC 的作用
下面一个Person类对象 有一个name 常量属性 一个初始化方法并赋值给name属性,一个析构方法
class Person {
let name: String
init(name: String) {
self.name = name
print("\(name) is being initialized")
}
deinit {
print("\(name) is being deinitialized")
}
}
定义三个Person? 类型的变量 reference1 reference2 reference3默认值为nil
var reference1: Person?
var reference2: Person?
var reference3: Person?
创建Person类的实例对象 reference1 强引用Person instance
reference1 = Person(name: "John Appleseed")
// Prints "John Appleseed is being initialized"
reference2 reference3 强引用Person instance
reference2 = reference1
reference3 = reference1
通过赋值nil给 reference1 reference2 使得Person instance引用变为1,ARC将不会释放 Person instance
reference1 = nil
reference2 = nil
当最后一个强引用设置为nil的时候,Person instance执行了析构函数
reference3 = nil
// Prints "John Appleseed is being deinitialized"
对象间的循环引用
在上面的例子🌰中,ARC能过追踪Person instance的引用计数,进行内存管理. 然而,我们很容易写出instance对象不存在强引用情况的代码,发生在两个class instances直接彼此强引用.(各位对方的属性)称为引用循环
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { print("\(name) is being deinitialized") }
}
class Apartment {
let unit: String
init(unit: String) { self.unit = unit }
var tenant: Person?
deinit { print("Apartment \(unit) is being deinitialized") }
}
定义Person Apartment变量 并初始化
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
初始化后 john unit4引用关系图
接下来给person