Swift ARC自動引用計數
Swift 內存管理功能是通過使用自動引用計數(ARC)來處理。ARC用於初始化和取消初始化所述系統資源,從而釋放使用的類實例的存儲器空間當實例不再需要。ARC跟蹤代碼的實例有效地管理存儲資源之間的關係的信息。
ARC的功能
在每一次一個新的類實例被創建時ARC分配一塊內存以存儲信息 init()
關於實例類型和其值的信息存儲在存儲器中
當類實例不再需要它自動由 deinit() 釋放,用於進一步類實例的存儲和檢索的存儲空間
ARC保存在磁道當前參照類實例的屬性,常量和變量,使得 deinit() 僅適用於那些不使用的實例。
ARC維護「強引用」這些類實例屬性,常量和變量來限制釋放噹噹前的類實例正在使用。
ARC 程序
class StudDetails { var stname: String! var mark: Int! init(stname: String, mark: Int) { self.stname = stname self.mark = mark } deinit { println("Deinitialized \(self.stname)") println("Deinitialized \(self.mark)") } } let stname = "swift" let mark = 98 println(stname) println(mark)
當我們使用 playground 運行上面的程序,得到以下結果。
swift
98
ARC 強參考週期類實例
class studmarks { let name: String var stud: student? init (name: String) { println("Initializing: \(name)") self.name = name } deinit { println("Deallocating: \(self.name)") } } class student { let name: String var strname: studmarks? init (name: String) { println("Initializing: \(name)") self.name = name } deinit { println("Deallocating: \(self.name)") } } var shiba: studmarks? var mari: student? shiba = studmarks(name: "Swift") mari = student(name: "ARC") shiba!.stud = mari
mari!.strname = shiba
當我們使用 playground 運行上面的程序,得到以下結果。
Initializing: Swift
Initializing: ARC
ARC弱和無主參考
Class類型屬性有兩種方法可以解決強引用週期:
弱引用
無主參考
這些引用是用來使一個實例指在一個基準週期其他實例。然後實例可以爲每一個實例參考代替處理強引用週期。當用戶知道某些情況下可能會返回 'nil' 值,我們可能會指向使用弱引用。當實例會返回不是零的東西,然後使用無主參考聲明。
弱引用程序
class module { let name: String init(name: String) { self.name = name } var sub: submodule? deinit { println("\(name) Is The Main Module") } } class submodule { let number: Int init(number: Int) { self.number = number } weak var topic: module? deinit { println("Sub Module with its topic number is \(number)") } } var toc: module? var list: submodule? toc = module(name: "ARC") list = submodule(number: 4) toc!.sub = list
list!.topic = toc
toc = nil list = nil
當我們使用 playground 運行上面的程序,得到以下結果。
ARC Is The Main Module
Sub Module with its topic number is 4
無主參考程序
class student { let name: String var section: marks? init(name: String) { self.name = name } deinit { println("\(name)") } } class marks { let marks: Int unowned let stname: student
init(marks: Int, stname: student) { self.marks \= marks self.stname \= stname } deinit { println("Marks Obtained by the student is \\(marks)") } } var module: student? module \= student(name: "ARC") module!.section \= marks(marks: 98, stname: module!) module \= nil
當我們使用 playground 運行上面的程序,得到以下結果。
ARC
Marks Obtained by the student is 98
閉包強引用週期
當我們分配一個閉包至類實例屬性,閉包的主體以捕獲特定實例強參考週期發生。強引用閉合由 self.someProperty 或 self.someMethod()定義。強引用週期用作閉包引用類型。
class HTMLElement { let samplename: String let text: String? lazy var asHTML: () -> String = { if let text = self.text { return "<\(self.samplename)>\(text)</\(self.samplename)>" } else { return "<\(self.samplename) />" } } init(samplename: String, text: String? = nil) { self.samplename = samplename self.text = text } deinit { println("\(samplename) is being deinitialized") } } var paragraph: HTMLElement? = HTMLElement(samplename: "p", text: "Welcome to Closure SRC") println(paragraph!.asHTML())
當我們使用 playground 運行上面的程序,得到以下結果。
Welcome to Closure SRC
弱和無主參考
當閉包和實例相互引用,用戶可以定義在一個閉合作爲無主引用捕獲。它不會允許用戶在同一時間解除分配實例。當實例在某個時候返回一個「nil」 定義並使用弱實例的值。
class HTMLElement { let module: String let text: String? lazy var asHTML: () -> String = { [unowned self] in if let text = self.text { return "<\(self.module)>\(text)</\(self.module)>" } else { return "<\(self.module) />" } } init(module: String, text: String? = nil) { self.module = module self.text = text } deinit { println("\(module) the deinit()") } } var paragraph: HTMLElement? = HTMLElement(module: "Inside", text: "ARC Weak References") println(paragraph!.asHTML()) paragraph = nil
當我們使用 playground 運行上面的程序,得到以下結果。
Inside the deinit()