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