Swift 强引用和弱引用
在本教程中,我们将通过示例了解 Swift 强引用和弱引用。
在 Swift 中,ARC(自动引用计数)自动处理内存的分配和释放。
但是,我们可以通过指定引用类型来防止 ARC 自动释放内存。例如,强引用保持对实例的固定控制,不允许 ARC 释放。
同样,弱引用不能保护实例不被 ARC 释放。
在学习强引用和弱引用之前,请确保了解 Swift中的类和对象 。
weak
关键字。Swift 的强引用
在 Swift 中,每当我们创建一个类的实例时,引用计数值都会从 0 增加到 1。同样,如果我们将实例释放,计数会减少到 0。让我们看一个实例,
class Employee {
var name: String
var colleague: Employee?
// define initializer
init(name : String) {
self.name = name;
}
}
// create two objects of Employee
var sabby: Employee? = Employee(name: "Sabby")
var cathy: Employee? = Employee(name: "Cathy")
在上面的实例中,我们创建了 Employee
类的实例:sabby
和 cathay
。现在 sabby
和 cathy
实例的引用计数都是 1。
这里,我们在类中创建了一个强引用。
var colleague: Employee?
现在,让我们使用这个引用将 sabby
的 colleague
属性引用给 cathy
。
sabby?.colleague = cathy
在这种情况下,为 cathy
创建了一个新的引用,将 cathy
的引用计数从 1 增加到 2。
同样,如果我们将 sabby
赋值给 cathy
的 colleague
,sabby
的引用计数将增加到 2。
cathy?.colleague = sabby
这里,sabby
和 cathy
实例的引用计数都是 2。
释放实例
在 Swift 中,只有当内存实例的引用计数为 0 时,才会释放内存实例。为了手动释放内存实例,我们将 nil
赋值给引用。例如,
sabby = nil
cathy = nil
当我们将 nil
赋值给实例时,实例的引用计数将减少 1。这里,上面的代码将 sabby
和 cathy
的引用计数减少 1。
然而,由于强引用,sabby
和 cathy
的引用计数都是 2,因此释放后的最终引用计数将是 1(2-1)。
这是 sabby
和 cathy
无法释放的强引用(引用计数不等于 0)。
nil
赋值给该类的对象。这就是我们使用 Employee?
而不是 Employee
的原因。实例:Swift 强引用
// declare a class
class Employee {
var name: String
var salary: Int
var colleague: Employee?
// define initializer
init(name: String, salary: Int) {
self.name = name
self.salary = salary
}
// define deinitializer
deinit {
print("Memory Deallocated")
}
}
// create instances of Employee
var sabby: Employee? = Employee(name: "Sabby", salary: 50000)
var cathy: Employee? = Employee(name: "Cathy", salary: 45000)
// increased reference count of cathy and sabby to 2
sabby?.colleague = cathy
cathy?.colleague = sabby
// deallocate objects
sabby = nil
cathy = nil
在上面的实例中,我们为 sabby
和 cathy
实例指定了 nil
。然而,sabby
和 cathy
是强引用,释放它们只会将引用计数从 2 减少到 1。
这就是为什么取消初始化
deinit {
print("Memory Deallocated")
}
没有调用,我们也没有得到任何输出。
如果我们想完全释放实例,我们会使用弱引用。
Swift 弱引用
如前所述,弱引用不能保护对象不被释放。这是因为当我们声明一个属性为弱属性时,该属性的引用计数永远不会超过 1。
class Employee {
weak var colleague: Employee?
...
}
这里,我们使用了 weak
关键字将同事表示为弱属性。
实例 2:弱引用
// declare a class
class Employee {
var name: String
var salary: Int
// weak property declaration
weak var colleague: Employee?
// define initializer
init(name: String, salary: Int) {
self.name = name
self.salary = salary
}
// define deinitializer
deinit {
print("Memory Deallocated")
}
}
// create instances of Employee
var sabby: Employee? = Employee(name: "Sabby", salary: 50000)
var cathy: Employee? = Employee(name: "Cathy", salary: 45000)
// colleague property of sabby instance refers to cathy instance
sabby?.colleague = cathy
// colleague property of cathy instance refers to sabby instance
cathy?.colleague = sabby
// deallocate objects
sabby = nil
cathy = nil
结果如下:
Memory Deallocated
Memory Deallocated
在上面的实例中,我们创建了 Employee
类的实例:sabby
和 cathay
。
var sabby: Employee? = Employee(name: "Sabby", salary: 50000)
var cathy: Employee? = Employee(name: "Cathy", salary: 45000)
现在 sabby
和 cathy
的参考计数都是 1。
这里,我们将 sabby
的同级属性转交给 cathy
,反之亦然。
sabby?.colleague = cathy
cathy?.colleague = sabby
在这种情况下,sabby
和 cathy
的引用计数都保持为 1,因为这次我们对同级属性使用了弱引用。
这就是我们释放了实例的原因。
sabby = nil
cathy = nil
引用被完全释放,并调用取消初始化。
deinit {
print("Memory Deallocated")
}
因此,最后输出 Memory Deallocated。