swift用自動引用計數(ARC)機制來對引用類型進行內存管理,(包括類實例和閉包)。
自動引用計數會引入循環強引用的問題。
解決循環強引用的辦法是弱引用和無主引用,分別用關鍵字weak和unknown來標示。
兩個類實例互相持有對方的強引用,因而每個實例都讓對方一直存在。
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") }
}
var john: Person?
var unit4A: Apartment?
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
john?.apartment = unit4A
unit4A?.tenant = john
print(john?.apartment?.unit)
print(unit4A?.tenant?.name)
john = nil
unit4A = nil
john和unit4A的析構器都沒有被調用。
解決辦法是將類Apartment的var tenant: Person?設成弱引用weak var tenant: Person?
閉包引起的循環強引用
class HTMLElement {
? ? let name: String
? ? let text: String?
? ? lazy var asHTML: (Void) -> String = {
? ? ? ? [unowned self] in
? ? ? ? if let text = self.text {
? ? ? ? ? ? return "<\(self.name)>\(text)"
? ? ? ? } else {
? ? ? ? ? ? ?return "<\(self.name) />"
? ? ? ? ?}
? ? }
? ? init(name: String, text: String? = nil) {
? ? ? ? self.name = name
? ? ? ? self.text = text
? ? }
? ? deinit {
? ? ? ? print("\(name) is being deinitialized")
? ? }
}