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