位置:首頁 > 高級語言 > Swift教學 > Swift ARC自動引用計數

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()