Swift 4語言中記憶體管理功能及用法通過自動引用計數(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 {
print("Deinitialized \(self.stname)")
print("Deinitialized \(self.mark)")
}
}
let stname = "Swift 4"
let mark = 98
print(stname)
print(mark)
當使用playground 運行上述程式時,得到以下結果 -
Swift 4
98
ARC強引用迴圈類實例
class studmarks {
let name: String
var stud: student?
init (name: String) {
print("Initializing: \(name)")
self.name = name
}
deinit {
print("Deallocating: \(self.name)")
}
}
class student {
let name: String
var strname: studmarks?
init (name: String) {
print("Initializing: \(name)")
self.name = name
}
deinit {
print("Deallocating: \(self.name)")
}
}
var shiba: studmarks?
var mari: student?
shiba = studmarks(name: "Swift 4")
mari = student(name: "ARC")
shiba!.stud = mari
mari!.strname = shiba
當使用playground 運行上述程式時,得到以下結果 -
Initializing: Swift 4
Initializing: ARC
ARC弱和無主引用
類類型屬性有兩種方法可以解決強引用週期 -
- 弱引用
- 無主引用
這些引用用於使一個實例能夠引用參考週期中的其他實例。 然後,實例可以參考每個實例而不是關注強引用迴圈。 當用戶知道某個實例可能返回nil
值時,可指出使用弱引用。 當實例返回某些內容而不是nil
時,則使用無主引用聲明它。
弱引用程式
class module {
let name: String
init(name: String) { self.name = name }
var sub: submodule?
deinit { print("\(name) Is The Main Module") }
}
class submodule {
let number: Int
init(number: Int) { self.number = number }
weak var topic: module?
deinit { print("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 { print("\(name)") }
}
class marks {
let marks: Int
unowned let stname: student
init(marks: Int, stname: student) {
self.marks = marks
self.stname = stname
}
deinit { print("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 {
print("\(samplename) is being deinitialized")
}
}
var paragraph: HTMLElement? = HTMLElement(samplename: "p", text: "Welcome to Closure SRC")
print(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 {
print("\(module) the deinit()")
}
}
var paragraph: HTMLElement? = HTMLElement(module: "Inside", text: "ARC Weak References")
print(paragraph!.asHTML())
paragraph = nil
當使用playground 運行上述程式時,得到以下結果 -
<Inside>ARC Weak References</Inside>
Inside the deinit()