如何工作
每个类实例都有一个引用计数,表示有多少个对象引用了这个实例。当引用计数变为零时,实例所占用的内存就会被释放。
- 增加引用计数:当一个新的引用指向实例时,引用计数会加一。
- 减少引用计数:当一个引用不再指向实例时,引用计数会减一。
Swift 使用强引用来管理引用计数,这意味着只要存在对实例的强引用,实例就不会被释放。
强引用
当你创建一个类的实例并将其赋值给一个变量或常量时,这个变量或常量就成为对实例的强引用。只要这个强引用还存在,实例就不会被释放。
class Person {
var name: String
init(name: String) {
self.name = name
}
}
var person1: Person? = Person(name: "John")
var person2: Person? = person1 // 增加了一个强引用
person1 = nil // 引用计数减一
person2 = nil // 引用计数减一,实例被释放
循环引用
当两个或多个实例相互保持强引用时,可能会形成循环引用。这会导致引用计数永远不会变为零,实例也永远不会被释放,从而造成内存泄漏。
Swift 提供了弱引用和无主引用来解决循环引用的问题。
弱引用和无主引用
- 弱引用(Weak References):不会保持实例的引用计数,当被引用的实例被释放时,弱引用会自动变为 nil。
class Apartment {
var tenant: Person?
}
class Person {
var apartment: Apartment?
}
var john: Person? = Person()
var unit4A: Apartment? = Apartment()
// 弱引用
john?.apartment = unit4A
unit4A?.tenant = john
john = nil // 引用计数减一,但因为是弱引用,不会影响引用计数
print(unit4A?.tenant) // 输出 nil
- 无主引用(Unowned References):也不会保持实例的引用计数,但假定被引用的实例在整个生命周期中不会被释放,否则可能引起运行时错误。
class Customer {
var card: CreditCard?
deinit {
print("Customer deinitialized")
}
}
class CreditCard {
// 无主引用
unowned let customer: Customer
init(customer: Customer) {
self.customer = customer
}
deinit {
print("CreditCard deinitialized")
}
}
var john: Customer? = Customer()
john?.card = CreditCard(customer: john!)
john = nil // 引用计数减一,但由于无主引用,不会影响引用计数,CreditCard 的实例会被正确释放
闭包引起的循环引用
当闭包捕获了实例时,也可能导致循环引用。在闭包中,使用 [unowned self] 或 [weak self] 来避免这种情况。
class HTMLElement {
let name: String
var text: String?
lazy var asHTML: () -> String = {
[unowned self] in // 或者 [weak self],根据实际情况选择
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) is being deinitialized")
}
}
var element: HTMLElement? = HTMLElement(name: "div", text: "Hello, World!")
print(element?.asHTML() ?? "") // 输出 "<div>Hello, World!</div>"
element = nil // 引用计数减一,HTMLElement 实例被释放
以上是一些关于 Swift 自动引用计数的基本用法。ARC 简化了内存管理,使得开发者无需手动管理内存,从而减少了内存泄漏和野指针的发生。
转载请注明出处:http://www.pingtaimeng.com/article/detail/14436/Swift