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 運行上麵的程序,得到以下結果。
<p>Welcome to Closure SRC</p>
弱和無主參考
當閉包和實例相互引用,用戶可以定義在一個閉合作為無主引用捕獲。它不會允許用戶在同一時間解除分配實例。當實例在某個時候返回一個“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>ARC Weak References</Inside> Inside the deinit()